Java集合(collections)框架提供了一组接口和类,以实现各种数据结构和算法。例如,集合框架的LinkedList类提供了双向链接列表数据结构的实现。
Collection 接口 Collection接口是集合框架的root根接口.
Java不提供Collection接口的直接实现,但是提供其子接口(如List,Set和Queue)的实现。
Collections 框架 Vs. Collection 接口 人们会对 Collections框架和Collection接口感到迷惑.
Collection接口是collections框架的根接口。该框架还包括其他接口:Map和Iterator,这些接口也可以具有子接口。
Collections接口的子接口 如前所述,Collection接口包括由Java类实现的子接口。
Collection接口的所有方法也都存在于其子接口中。
这是收集接口的子接口:
List Interface List接口是一个有序的集合,它允许我们添加和删除数组之类的元素。
Set Interface Set接口允许我们将元素存储在不同的集合中,类似于数学中的集合。它不能有重复的元素。
Queue Interface 当我们要以First In, First Out(FIFO)(先进先出)的方式存储和访问元素时,可以使用Queue接口。
Map Interface 在Java中,Map接口允许将元素存储在key/value对中。key是唯一的名称,可用于访问Map中的特定元素。
Iterator Interface 在Java中,Iterator接口提供了可用于访问集合元素的方法。
为什么用 Collections 框架 Java集合框架提供了可以直接使用的各种数据结构和算法。这有两个主要优点:
我们不必编写代码即可手动实现这些数据结构和算法。
随着集合框架的高度优化,我们的代码将更加高效。
此外,集合框架允许我们对特定类型的数据使用特定的数据结构。这里有一些例子:
如果我们希望数据唯一,则可以使用collections框架提供的Set接口。
要将数据存储在key/value对中,我们可以使用Map接口。
ArrayList类提供可调整大小的数组的功能。
Collections例子: ArrayList Class ArrayList类允许我们创建可调整大小的数组。该类实现List接口(这是Collection接口的子接口)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayList: " + animals); } }
输出:
1 ArrayList: [Dog, Cat, Horse]
Collection 中的方法 Collection接口包括各种方法,可用于对对象执行不同的操作.这些方法在其所有子接口中均可用。
add() - 将指定的元素插入到集合中
size() - 返回集合的大小
remove() - 从集合中删除指定的元素
iterator() - 返回用于访问集合元素的迭代器
addAll() - 将指定集合的所有元素添加到集合中
removeAll() - 从集合中删除指定集合的所有元素
clear() - 删除集合的所有元素
在Java中,List接口是一个有序的集合,允许我们按顺序存储和访问元素。它扩展了Collection接口。
实现List接口的类 由于List是一个接口,因此我们无法从中创建对象。 为了使用List接口的功能,我们可以使用以下类:
这些类在Collections框架中定义,并实现List接口。
如何使用List 在Java中,必须导入java.util.List包才能使用List。
1 2 3 4 5 List<String> list1 = new ArrayList<>(); List<String> list2 = new LinkedList<>();
在这里,我们创建了ArrayList和LinkedList类的对象list1和list2。这些对象可以使用List接口的功能。
List 中的方法 List接口包括Collection接口的所有方法。这是因为Collection是List的父级接口。
List接口中还提供了Collection接口的一些常用方法:
add() - 向list添加一个元素.
addAll() - 将一个列表中的所有元素添加进另一个列表中.
get() - 帮助随机访问列表中的元素.
iterator() - 返回可用于顺序访问列表元素的迭代器对象.
set() - 更改列表元素.
remove() - 从列表中删除一个元素.
removeAll() - 从列表中删除所有元素.
clear() - 从列表中删除所有元素(比removeAll()更有效).
size() - 返回列表的长度.
toArray() - 将列表转换为数组.
contains() - 如果列表包含指定的元素,则返回true.
List 接口的实现 ArrayList 类实现1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.List;import java.util.ArrayList;class Main { public static void main (String[] args) { List<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("List: " + numbers); int number = numbers.get(2 ); System.out.println("Accessed Element: " + number); int removedNumber = numbers.remove(1 ); System.out.println("Removed Element: " + removedNumber); } }
输出:
1 2 3 List: [1 , 2 , 3 ] Accessed Element: 3 Removed Element: 2
LinkedList类实现1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.List;import java.util.LinkedList;class Main { public static void main (String[] args) { List<Integer> numbers = new LinkedList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("List: " + numbers); int number = numbers.get(2 ); System.out.println("Accessed Element: " + number); int index = numbers.indexOf(2 ); System.out.println("Position of 3 is " + index); int removedNumber = numbers.remove(1 ); System.out.println("Removed Element: " + removedNumber); } }
输出:
1 2 3 4 List: [1 , 2 , 3 ] Accessed Element: 3 Position of 3 is 1 Removed Element: 2
Java List VS Set List接口和Set接口都继承了Collection接口。但是,它们之间存在一些差异。
List可以包含重复的元素。但是,Set`不能有重复的元素。
List中的元素以某种顺序存储。但是,Set中的元素像数学中的集合一样按组存储。
ArrayList类,在Java集合框架中提供了可以调整数组大小功能.
ArrayList Vs Array 在Java中, 我们需要先声明数组的大小,再使用它.当数组的大小一旦定义,你就很难去改变它.
为了解决这个问题,我们可以使用ArrayList,它允许我们创建可调整大小的数组。
ArrayList会自动的在我们新增或删除元素的时候动态调整它的大小.因此ArrayList也被称为动态数组.
创建 一个ArrayList 在使用ArrayList之前,我们需要首先导入java.util.ArrayList包。
创建arraylist语法:
1 ArrayList<Type> arrayList= new ArrayList<>();
Type表示arrayList中元素类型.
1 2 3 4 5 ArrayList<Integer> arrayList = new ArrayList<>(); ArrayList<String> arrayList = new ArrayList<>();
在上面的程序中,我们使用了Integer 并不能进行初始化。这是因为我们在创建arraylist时不能使用基本类型。我们应该使用相应的包装器类 。
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("Swift" ); System.out.println("ArrayList: " + languages); } }
输出:
1 ArrayList: [Java, Python, Swift]
在上面的示例中,我们创建了一个名为language的ArrayList。
在这里,我们使用了add()方法将元素添加到arraylist中。
我们还可以使用List接口创建一个arraylist。这是因为ArrayList类实现了List接口。
1 List<String> list = new ArrayList<>();
ArrayList 基本操作 ArrayList提供了各种对arraylist操作的方法.
添加元素到 ArrayList 要将单个元素添加到arraylist,我们使用ArrayList类的add()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("C" ); languages.add("Python" ); System.out.println("ArrayList: " + languages); languages.add(1 , "JavaScript" ); System.out.println("Updated ArrayList: " + languages); } }
输出:
1 2 ArrayList: [Java, C, Python] Updated ArrayList: [Java, JavaScript, C, Python]
在上面的示例中,我们创建了一个名为language的ArrayList。在这里,我们使用add()方法将元素添加到语言中。
注意声明:
1 languages.add(1 , "JavaScript" );
在这里,我们使用了索引号参数。它是一个可选参数,用于指定添加新元素的位置。
获取ArrayList中一个元素 要访问arraylist中的元素,我们使用ArrayList类的get()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Cat" ); animals.add("Dog" ); animals.add("Cow" ); System.out.println("ArrayList: " + animals); String str = animals.get(1 ); System.out.print("Element at index 1: " + str); } }
输出
1 2 ArrayList: [Cat, Dog, Cow] Element at index 1 : Dog
在上面的示例中,我们使用了带有参数1的get()方法。这里,该方法返回索引为1的元素。
修改ArrayList中的元素 要更改arraylist的元素,我们使用ArrayList类的set()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Kotlin" ); languages.add("C++" ); System.out.println("ArrayList: " + languages); languages.set(2 , "JavaScript" ); System.out.println("Modified ArrayList: " + languages); } }
输出:
1 2 ArrayList: [Java, Kotlin, C++] Modified ArrayList: [Java, Kotlin, JavaScript]
在上面的示例中,我们创建了一个名为language的ArrayList。但是通过language.set(2,'JavaScript').我们修改了下标2的元素值为JavaScript.
移除ArrayList中元素 要从arraylist中删除一个元素,我们可以使用ArrayList类的remove()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> animals = new ArrayList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayList: " + animals); String str = animals.remove(2 ); System.out.println("Updated ArrayList: " + animals); System.out.println("Removed Element: " + str); } }
输出
1 2 3 ArrayList: [Dog, Cat, Horse] Updated ArrayList: [Dog, Cat] Removed Element: Horse
在这里,remove()方法将索引号 作为参数,删除索引编号下的元素.
ArrayList中的常用方法
遍历ArrayList 可以使用for-each遍历ArrayList
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Cow" ); languages.add("Cat" ); languages.add("Dog" ); System.out.println("ArrayList: " + languages); System.out.println("Accessing individual elements: " ); for (String language : languages) { System.out.print(language); System.out.print(", " ); } } }
输出:
1 2 3 ArrayList: [Cow, Cat, Dog] Accessing individual elements: Cow, Cat, Dog,
ArrayList转成Array我们可以使用toArray()方法将ArrayList转换为Array。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("C++" ); System.out.println("ArrayList: " + languages); String[] arr = new String[languages.size()]; languages.toArray(arr); System.out.print("Array: " ); for (String item : arr) { System.out.print(item + ", " ); } } }
输出:
1 2 ArrayList: [Java, Python, C++] Array: Java, Python, C++,
在上面的示例中,我们创建了一个名为language的数组列表。注意声明:
在这里,toArray()方法将arraylist转换为数组并将其存储在arr中。
Array转成ArrayList我们还可以将Array转换为arraylist。为此,我们使用Arrays类的asList()方法。
要使用asList(),我们必须首先导入java.util.Arrays包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Arrays;class Main { public static void main (String[] args) { String[] arr = { "Java" , "Python" , "C++" }; System.out.print("Array: " ); for (String str : arr) { System.out.print(str); System.out.print(" " ); } ArrayList<String> languages = new ArrayList<>(Arrays.asList(arr)); System.out.println("\nArrayList: " + languages); } }
输出:
1 2 Array: Java Python C++ ArrayList: [Java, Python, C++]
注意:我们还可以使用Arrays.asList()方法在一行中创建和初始化arraylist。例如,
1 ArrayList<String> animals = new ArrayList<>(Arrays.asList("Cat" , "Cow" , "Dog" ));
ArrayList转成 String我们可以使用ArrayList类的toString()方法将arraylist转换为字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<String> languages = new ArrayList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("Kotlin" ); System.out.println("ArrayList: " + languages); String str = languages.toString(); System.out.println("String: " + str); } }
输出:
1 2 ArrayList: [Java, Python, Kotlin] String: [Java, Python, Kotlin]
在这里,toString()方法将整个arraylist转换为单个字符串。
Vector类是List接口的一种实现,它使我们可以创建类似于ArrayList类的可调整大小的数组。
Vectorvs.ArrayListArrayList和Vector均实现List接口并提供相同的功能。但是,它们之间存在一些差异。
Vector类同步每个单独的操作。这意味着每当我们要对向量执行某些操作时,Vector类都会自动对该操作施加锁定。
这是因为当一个线程正在访问向量时,同时另一个线程试图访问它时,会生成一个称为ConcurrentModificationException的异常。但是这样每次操作进行锁操作会降低整个的性能.
但是,在array list中方法不同步。但可以使用Collections.synchronizedList()方法将整个列表同步。
注意:建议使用ArrayList代替Vector,因为矢量不是线程安全的,并且效率较低。
创建 一个 Vector 1 Vector<Type> vector = new Vector<>();
此处,Type表示链接列表的类型。
1 2 3 4 5 Vector<Integer> vector= new Vector<>(); Vector<String> vector= new Vector<>();
Vector中的方法Vector类还提供List接口的可调整大小的数组实现(类似于ArrayList类)。一些Vector方法是:
向Vector中添加元素
add(element) - 向Vector中添加元素.
add(index,element) - 向Vector中指定位置添加元素.
addAll(vector) - 将一个Vector中所有元素添加另一个Vector中.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> mammals= new Vector<>(); mammals.add("Dog" ); mammals.add("Horse" ); mammals.add(2 , "Cat" ); System.out.println("Vector: " + mammals); Vector<String> animals = new Vector<>(); animals.add("Crocodile" ); animals.addAll(mammals); System.out.println("New Vector: " + animals); } }
输出:
1 2 Vector: [Dog, Horse, Cat] New Vector: [Crocodile, Dog, Horse, Cat]
获取Vector中的元素
get(index) - 返回指定下标下的元素
iterator() - 返回一个迭代器对象以顺序访问vector中元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Iterator;import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> animals= new Vector<>(); animals.add("Dog" ); animals.add("Horse" ); animals.add("Cat" ); String element = animals.get(2 ); System.out.println("Element at index 2: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("Vector: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 Element at index 2 : Cat Vector: Dog, Horse, Cat,
移除Vector中的元素
remove(index) - 从指定位置删除元素.
removeAll() - 移除所有的元素.
clear() - 删除所有元素。它比removeAll()性能更好.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.Vector;class Main { public static void main (String[] args) { Vector<String> animals= new Vector<>(); animals.add("Dog" ); animals.add("Horse" ); animals.add("Cat" ); System.out.println("Initial Vector: " + animals); String element = animals.remove(1 ); System.out.println("Removed Element: " + element); System.out.println("New Vector: " + animals); animals.clear(); System.out.println("Vector after clear(): " + animals); } }
输出:
1 2 3 4 Initial Vector: [Dog, Horse, Cat] Removed Element: Horse New Vector: [Dog, Cat] Vector after clear () : []
其它Vector方法
Methods
Descriptions
set()
更改Vector的元素
size()
返回Vector中的大小
toArray()
将Vector转换为数组
toString()
将Vector转换为字符串
contains()
在Vector中搜索指定的元素并返回布尔结果
Stack类 Java集合框架具有一个名为Stack的类,该类提供堆栈数据结构的功能。
Stack类扩展了Vector类。
Stack 实现 在Stack中元素遵循Last In First Out后进先出的原则.元素被添加到堆栈的顶部,并从堆栈的顶部移除。
创建一个 Stack 为了创建堆栈,我们必须首先导入java.util.Stack包。导入包后,就可以使用Java创建堆栈。
1 Stack<Type> stacks = new Stack<>();
在这里,Type表示堆栈的类型
1 2 3 4 5 Stack<Integer> stacks = new Stack<>(); Stack<String> stacks = new Stack<>();
Stack 中的方法 由于Stack扩展了Vector类,因此它继承了Vector的所有方法。
除了这些方法之外,Stack类还包括5个与Vector区别开来的方法。
push() 方法 要将元素添加到stack的顶部,我们使用push()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); } }
输出:
1 Stack: [Dog, Horse, Cat]
pop() 方法 若要从堆栈顶部删除元素,我们使用 pop() 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Initial Stack: " + animals); String element = animals.pop(); System.out.println("Removed Element: " + element); } }
输出:
1 2 Initial Stack: [Dog, Horse, Cat] Removed Element: Cat
peek() 方法 peek() 方法从堆栈顶部返回对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); String element = animals.peek(); System.out.println("Element at top: " + element); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Element at top: Cat
search 方法 若要搜索堆栈中的元素,我们使用 search() 方法。它会返回元素所在下标.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); int position = animals.search("Horse" ); System.out.println("Position of Horse: " + position); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Position of Horse: 2
empty()方法 为了检查堆栈是否为空,我们使用 empty() 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.Stack;class Main { public static void main (String[] args) { Stack<String> animals= new Stack<>(); animals.push("Dog" ); animals.push("Horse" ); animals.push("Cat" ); System.out.println("Stack: " + animals); boolean result = animals.empty(); System.out.println("Is the stack empty? " + result); } }
输出:
1 2 Stack: [Dog, Horse, Cat] Is the stack empty? false
用 ArrayDeque替代Stack Stack类提供了堆栈数据结构的直接实现。但是,建议不要使用它。而是使用ArrayDeque类(实现Deque接口).在Java中实现堆栈数据结构。
Queue 接口 Java collections框架通过Queue接口提供了队列数据结构的功能。它继承至Collection.
实现Queue的接口 为了使用Queue的功能,我们需要使用实现它的类:
扩展Queue的接口 Queue接口还通过各种子接口扩展:
Deque
BlockingQueue
BlockingDeque
Queue数据结构工作模式 在Queue队列中,以(First In, First Out)先进先出的方式存储和访问元素。
元素从后面添加,从前面删除。
怎么使用队列 在Java中,必须导入java.util.Queue包才能使用Queue。
1 2 3 4 5 6 7 8 9 Queue<String> animal1 = new LinkedList<>(); Queue<String> animal2 = new ArrayDeque<>(); Queue<String> animal 3 = new PriorityQueue<>();
在这里,我们分别创建了类LinkedList,ArrayDeque和PriorityQueue的对象Animal1,Animal2和Animal3。这些对象可以使用Queue接口的功能。
Queue中的方法 Queue接口包括Collection接口的所有方法。
Queue接口的一些常用方法是:
add() - 将指定的元素插入队列。如果任务成功,则add()返回true,否则返回异常。
offer() - 将指定的元素插入队列。如果任务成功,则offer()返回true,否则返回false。
element() - 返回队列的头元素。如果队列为空,则引发异常。
peek() - 返回队列的头元素。如果队列为空,则返回null。
remove() - 返回并删除队列的头元素。如果队列为空,则引发异常。
poll() - 返回并删除队列的头元素.如果队列为空,则返回null。
实现Queue接口 LinkedList类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.Queue;import java.util.LinkedList;class Main { public static void main (String[] args) { Queue<Integer> numbers = new LinkedList<>(); numbers.offer(1 ); numbers.offer(2 ); numbers.offer(3 ); System.out.println("Queue: " + numbers); int accessedNumber = numbers.peek(); System.out.println("Accessed Element: " + accessedNumber); int removedNumber = numbers.poll(); System.out.println("Removed Element: " + removedNumber); System.out.println("Updated Queue: " + numbers); } }
输出:
1 2 3 4 Queue: [1 , 2 , 3 ] Accessed Element: 1 Removed Element: 1 Updated Queue: [2 , 3 ]
PriorityQueue类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.Queue;import java.util.PriorityQueue;class Main { public static void main (String[] args) { Queue<Integer> numbers = new PriorityQueue<>(); numbers.offer(5 ); numbers.offer(1 ); numbers.offer(2 ); System.out.println("Queue: " + numbers); int accessedNumber = numbers.peek(); System.out.println("Accessed Element: " + accessedNumber); int removedNumber = numbers.poll(); System.out.println("Removed Element: " + removedNumber); System.out.println("Updated Queue: " + numbers); } }
输出:
1 2 3 4 Queue: [1 , 5 , 2 ] Accessed Element: 1 Removed Element: 1 Updated Queue: [2 , 5 ]
PriorityQueue类提供堆数据结构的功能。
与普通队列不同,优先级队列元素是按排序顺序检索的。
假设我们要按升序检索元素。在这种情况下,优先级队列的头部将是最小的元素。一旦检索到此元素,下一个最小的元素将是队列的开头。
重要的是要注意,优先级队列的元素可能未排序。但是,元素总是按排序顺序检索。
创建 PriorityQueue 为了创建优先级队列,我们必须导入java.util.PriorityQueue包。导入程序包后,可以使用以下方法在Java中创建优先级队列。
1 PriorityQueue<Integer> numbers = new PriorityQueue<>();
在这里,我们创建了一个没有任何参数的优先级队列。在这种情况下,优先级队列的头部是队列的最小元素。并且元素以升序从队列中删除。
但是,我们可以借助Comparator接口自定义元素的顺序。
PriorityQueue中的方法PriorityQueue类提供了Queue接口中存在的所有方法的实现。
PriorityQueue插入元素
add() - 将指定的元素插入队列。如果队列已满,则将引发异常。
offer() - 将指定的元素插入队列。如果队列已满,则返回false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); System.out.println("PriorityQueue: " + numbers); numbers.offer(1 ); System.out.println("Updated PriorityQueue: " + numbers); } }
输出:
1 2 PriorityQueue: [2 , 4 ] Updated PriorityQueue: [1 , 4 , 2 ]
在这里,我们创建了一个名为数字的优先级队列。我们已将4和2插入队列。
尽管在2之前插入了4,但队列的开头是2。这是因为优先级队列的头是队列中最小的元素。
然后,我们将1插入队列。现在重新排列了队列,以将最小的元素1存储到队列的开头。
PriorityQueue获取元素要访问优先级队列中的元素,我们可以使用peek()方法。此方法返回队列的头元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.println("PriorityQueue: " + numbers); int number = numbers.peek(); System.out.println("Accessed Element: " + number); } }
输出:
1 2 PriorityQueue: [1 , 4 , 2 ] Accessed Element: 1
移除PriorityQueue中的元素
romve() - 从队列中删除指定的元素.
poll() - 返回并删除队列的开头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.PriorityQueue;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.println("PriorityQueue: " + numbers); boolean result = numbers.remove(2 ); System.out.println("Is the element 2 removed? " + result); int number = numbers.poll(); System.out.println("Removed Element Using poll(): " + number); } }
输出:
1 2 3 PriorityQueue: [1 , 4 , 2 ] Is the element 2 removed? true Removed Element Using poll () : 1
遍历 PriorityQueue 要遍历优先级队列的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.PriorityQueue;import java.util.Iterator;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); System.out.print("PriorityQueue using iterator(): " ); Iterator<Integer> iterate = numbers.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 PriorityQueue using iterator () : 1, 4, 2,
其它PriorityQueue方法
Methods
Descriptions
contains(element)
在优先级队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size()
返回优先级队列的长度。
toArray()
将优先级队列转换为数组并返回它。
PriorityQueue Comparator Priority元素以自然顺序(升序)检索。但是,我们可以自定义此排序。
为此,我们需要创建自己的比较器类来实现Comparator接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.PriorityQueue;import java.util.Comparator;class Main { public static void main (String[] args) { PriorityQueue<Integer> numbers = new PriorityQueue<>(new CustomComparator()); numbers.add(4 ); numbers.add(2 ); numbers.add(1 ); numbers.add(3 ); System.out.print("PriorityQueue: " + numbers); } } class CustomComparator implements Comparator <Integer > { @Override public int compare (Integer number1, Integer number2) { int value = number1.compareTo(number2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } }
输出
1 PriorityQueue: [4 , 3 , 1 , 2 ]
在上面的示例中,我们创建了一个priorty队列,将CustomComparator类作为参数传递。
CustomComparator类实现Comparator接口。
然后,我们重写compare()方法。现在,该方法使元素的头元素为最大数。
Java collections框架Deque提供了双端队列功能.它继承至Queue接口.
Deque工作模式
在常规队列中,元素是从后面添加的,而从前面删除的。但是,在双端队列中,我们可以从前面和后面插入和删除元素(insert and remove elements from both front and rear)
Deque接口的实现为了使用Deque接口的功能,我们需要使用实现该接口的类:
怎么使用 Deque 在Java中,我们必须导入java.util.Deque包才能使用Deque。
1 2 3 4 5 Deque<String> animal1 = new ArrayDeque<>(); Deque<String> animal2 = new LinkedList<>();
在这里,我们分别创建了类ArrayDeque和LinkedList的对象animal1和animal2。
Deque中的方法Deque继承至Queue接口,它继承了所有Queue接口.
除Queue接口中可用的方法外,Deque接口还包括以下方法:
addFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则引发异常。
addLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则引发异常.
offerFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则返回false。
offerLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则返回false。
getFirst() - 返回双端队列的第一个元素。如果双端队列为空,则引发异常。
getLast() - 返回双端队列的最后一个元素。如果双端队列为空,则引发异常。
peekFirst() - 返回双端队列的第一个元素。如果双端队列为空,则返回null。
peekLast() - 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
removeFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则引发异常。
removeLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则引发异常。
pollFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则返回null。
pollLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则返回null。
Deque 作为堆栈数据结构 Java Collections框架的Stack类提供了堆栈的实现。
但是,建议将Deque用作堆栈而不是Stack类。这是因为Stack的方法是同步的。
以下是Deque接口提供的用于实现堆栈的方法:
push() - 在双端队列的开头添加一个元素
pop()- 从双端队列的开头删除元素
peek() - 从双端队列的开头返回一个元素
实现Deque了类ArrayDeque 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.Deque;import java.util.ArrayDeque;class Main { public static void main (String[] args) { Deque<Integer> numbers = new ArrayDeque<>(); numbers.offer(1 ); numbers.offerLast(2 ); numbers.offerFirst(3 ); System.out.println("Deque: " + numbers); int firstElement = numbers.peekFirst(); System.out.println("First Element: " + firstElement); int lastElement = numbers.peekLast(); System.out.println("Last Element: " + lastElement); int removedNumber1 = numbers.pollFirst(); System.out.println("Removed First Element: " + removedNumber1); int removedNumber2 = numbers.pollLast(); System.out.println("Removed Last Element: " + removedNumber2); System.out.println("Updated Deque: " + numbers); } }
输出:
1 2 3 4 5 6 Deque: [3 , 1 , 2 ] First Element: 3 Last Element: 2 Removed First Element: 3 Removed Last Element: 2 Updated Deque: [1 ]
Javacollections框架的LinkedList类提供了链表数据结构(双重链表)的功能。
链表中的每个元素都称为节点。它包含3个字段:
Prev - 将前一个元素的地址存储在列表中。第一个元素为null
Next- 在列表中存储下一个元素的地址。最后一个元素为null
Data- 存储实际数据.
创建 Java LinkedList 这是我们如何在Java中创建链接列表的方法:
1 LinkedList<Type> linkedList = new LinkedList<>();
此处,Type表示链接列表的类型。
1 2 3 4 5 LinkedList<Integer> linkedList = new LinkedList<>(); LinkedList<String> linkedList = new LinkedList<>();
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); System.out.println("LinkedList: " + animals); } }
输出
1 LinkedList: [Dog, Cat, Cow]
在上面的示例中,我们创建了一个名为Animals的LinkedList。
在这里,我们使用add()方法将元素添加到LinkedList。
LinkedList 中的工作模式 链接列表中的元素未按顺序存储。相反,它们分散并通过链接(上一个和下一个)连接。
在这里,链接列表中包含3个元素。
Dog - 它是第一个保留null为上一个地址,而Cat的地址为下一个地址的元素
Cat - 它是第二个元素,将Dog的地址作为前一个地址,将Cow的地址作为下一个地址
Cow-它是将Cat的地址保留为前一个地址而将null保留为下一个元素的最后一个元素
LinkedList 中的方法LinkedList提供了多种方法,使我们可以在链表中执行不同的操作。
向 LinkedList中添加元素 我们可以使用add()方法在LinkedList的末尾添加一个元素(节点)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); System.out.println("LinkedList: " + animals); animals.add(1 , "Horse" ); System.out.println("Updated LinkedList: " + animals); } }
输出:
1 2 LinkedList: [Dog, Cat, Cow] Updated LinkedList: [Dog, Horse, Cat, Cow]
在上面的示例中,我们创建了一个名为Animals的LinkedList。在这里,我们使用add()方法向动物添加元素。
注意:
1 animals.add(1 , "Horse" );
在这里,我们使用了索引号参数,它是一个可选参数,用于指定添加新元素的位置。
获取 LinkedList元素 LinkedList类的get()方法用于访问LinkedList中的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Python" ); languages.add("Java" ); languages.add("JavaScript" ); System.out.println("LinkedList: " + languages); String str = languages.get(1 ); System.out.print("Element at index 1: " + str); } }
输出
1 2 LinkedList: [Python, Java, JavaScript] Element at index 1 : Java
在上面的示例中,我们将get()方法的参数1一起使用。在这里,该方法返回索引为1的元素。
我们还可以使用iterator()和listIterator()方法访问LinkedList的元素。
修改LinkedList中的元素 LinkedList类的set()方法用于更改LinkedList的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("JavaScript" ); languages.add("Java" ); System.out.println("LinkedList: " + languages); languages.set(3 , "Kotlin" ); System.out.println("Updated LinkedList: " + languages); } }
输出:
1 2 LinkedList: [Java, Python, JavaScript, Java] Updated LinkedList: [Java, Python, JavaScript, Kotlin]
1 languages.set(3 , "Kotlin" );
在这里,set()方法将索引3处的元素更改为Kotlin。
移除LinkedList中的元素 LinkedList类的remove()方法用于从LinkedList中删除元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> languages = new LinkedList<>(); languages.add("Java" ); languages.add("Python" ); languages.add("JavaScript" ); languages.add("Kotlin" ); System.out.println("LinkedList: " + languages); String str = languages.remove(1 ); System.out.println("Removed Element: " + str); System.out.println("Updated LinkedList: " + languages); } }
输出:
1 2 3 LinkedList: [Java, Python, JavaScript, Kotlin] Removed Element: Python New LinkedList: [Java, JavaScript, Kotlin]
在这里,remove()方法将索引号作为参数。并且删除索引编号指定的元素。
其它常用方法
Methods
Description
contains()
检查LinkedList是否包含元素
indexOf()
返回元素第一次出现的索引
lastIndexOf()
返回元素最后一次出现的索引
clear()
删除LinkedList的所有元素
iterator()
返回用于迭代LinkedList的迭代器
LinkedList 作为 Deque 和Queue 由于LinkedList类还实现了Queue和Deque接口,它也可以实现这些接口的方法。
以下是一些常用方法:
Methods
Descriptions
addFirst()
将指定的元素添加到链接列表的开头
addLast()
将指定的元素添加到链接列表的末尾
getFirst()
返回第一个元素
getLast()
返回最后一个元素
removeFirst()
删除第一个元素
removeLast()
删除最后一个元素
peek()
返回链表的第一个元素(头)
poll()
返回并从链接列表中删除第一个元素
offer()
将指定的元素添加到链接列表的末尾
LinkedList 作为 Queue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.LinkedList;import java.util.Queue;class Main { public static void main (String[] args) { Queue<String> languages = new LinkedList<>(); languages.add("Python" ); languages.add("Java" ); languages.add("C" ); System.out.println("LinkedList: " + languages); String str1 = languages.peek(); System.out.println("Accessed Element: " + str1); String str2 = languages.poll(); System.out.println("Removed Element: " + str2); System.out.println("LinkedList after poll(): " + languages); languages.offer("Swift" ); System.out.println("LinkedList after offer(): " + languages); } }
输出:
1 2 3 4 5 LinkedList: [Python, Java, C] Accessed Element: Python Removed Element: Python LinkedList after poll () : [Java, C] LinkedList after offer () : [Java, C, Swift]
LinkedList as Deque 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.LinkedList;import java.util.Deque;class Main { public static void main (String[] args) { Deque<String> animals = new LinkedList<>(); animals.add("Cow" ); System.out.println("LinkedList: " + animals); animals.addFirst("Dog" ); System.out.println("LinkedList after addFirst(): " + animals); animals.addLast("Zebra" ); System.out.println("LinkedList after addLast(): " + animals); animals.removeFirst(); System.out.println("LinkedList after removeFirst(): " + animals); animals.removeLast(); System.out.println("LinkedList after removeLast(): " + animals); } }
输出:
1 2 3 4 5 LinkedList: [Cow] LinkedList after addFirst () : [Dog, Cow] LinkedList after addLast () : [Dog, Cow, Zebra] LinkedList after removeFirst () : [Cow, Zebra] LinkedList after removeLast () : [Cow]
遍历 LinkedList 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedList;class Main { public static void main (String[] args) { LinkedList<String> animals = new LinkedList<>(); animals.add("Cow" ); animals.add("Cat" ); animals.add("Dog" ); System.out.println("LinkedList: " + animals); System.out.println("Accessing linked list elements:" ); for (String animal: animals) { System.out.print(animal); System.out.print(", " ); } } }
输出:
1 2 3 LinkedList: [Cow, Cat, Dog] Accessing linked list elements: Cow, Cat, Dog,
LinkedList Vs. ArrayList Java ArrayList和LinkedList都实现Collections框架的List接口。但是,它们之间存在一些差异。
LinkedList
ArrayList
实现List,Queue和Deque接口。
实现List接口
一个单位会存三个值
一个单位存一个值
提供双向链表实现
提供可调整大小的数组实现
每当添加元素时,上一个和下一个地址都会更改
每当添加元素时,该位置之后的所有元素都会移动
要访问元素,我们需要从头开始迭代到元素
可以使用索引随机访问元素
在Java中我们可以通过接口创建LinkedList
1 2 3 4 5 6 7 8 List<String> animals1 = new LinkedList<>(); Queue<String> animals2 = new LinkedList<>(); Deque<String> animals3 = new LinkedList<>();
在这里,如果LinkedList是使用一个接口创建的,则我们不能使用其他接口提供的方法。也就是说,animals1不能使用特定于Queue和Deque接口的方法。
在Java中,我们可以使用ArrayDeque类使用数组来实现队列和双端队列数据结构。
ArrayDeque实现了Queue和Deque接口
创建 ArrayDeque 为了创建数组双端队列,我们必须导入java.util.ArrayDeque包。
1 ArrayDeque<Type> animal = new ArrayDeque<>();
在此,Type表示数组双端队列的类型。
1 2 3 4 5 ArrayDeque<String> animals = new ArrayDeque<>(); ArrayDeque<Integer> age = new ArrayDeque<>();
ArrayDeque 中的方法 ArrayDeque类为Queue和Deque接口中存在的所有方法提供实现。
Deque插入元素 添加元素通过 add()、addFirst()、addLast()
add() - 在数组双端队列的末尾插入指定的元素
addFirst() - 在数组双端队列的开始处插入指定的元素
addLast() - 在数组双端队列的末尾插入指定的
注意: 如果数组双端队列已满,则所有这些方法add(),addFirst()和addLast()都会引发IllegalStateException。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.addFirst("Cat" ); animals.addLast("Horse" ); System.out.println("ArrayDeque: " + animals); } }
输出:
1 ArrayDeque: [Cat, Dog, Horse]
插入数据offer()、offerFirst()、offerLast()
offer() - 在数组双端队列的末尾插入指定的元素
offerFirst() - 在数组双端队列的开始处插入指定的元素
offerLast() - 在数组双端队列的末尾插入指定的元素
注意: 如果成功插入元素,则offer(),offerFirst()和offerLast()返回true;否则,返回true。如果数组双端队列已满,则这些方法将返回false。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.offer("Dog" ); animals.offerFirst("Cat" ); animals.offerLast("Horse" ); System.out.println("ArrayDeque: " + animals); } }
输出:
1 ArrayDeque: [Cat, Dog, Horse]
注意: 如果阵列双端队列已满
add()方法将引发异常
offer()方法返回false
获取ArrayDeque元素 获取元素getFirst()和getLast()
getFirst() - 返回数组双端队列的第一个元素
getLast() - 返回数组双端队列的最后一个元素
注意: 如果数组双端队列为空,则getFirst()和getLast()引发NoSuchElementException。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String firstElement = animals.getFirst(); System.out.println("First Element: " + firstElement); String lastElement = animals.getLast(); System.out.println("Last Element: " + lastElement); } }
输出:
1 2 3 ArrayDeque: [Dog, Cat, Horse] First Element: Dog Last Element: Horse
使用peek(),peekFirst()和peekLast()方法获取元素
peek() - 返回数组双端队列的第一个元素
peekFirst() - 返回数组双端队列的第一个元素(与peek()等效)
peekLast()-返回数组双端队列的最后一个元素
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.peek(); System.out.println("Head Element: " + element); String firstElement = animals.peekFirst(); System.out.println("First Element: " + firstElement); String lastElement = animals.peekLast(); System.out.println("Last Element: " + lastElement); } }
输出:
1 2 3 4 ArrayDeque: [Dog, Cat, Horse] Head Element: Dog First Element: Dog Last Element: Horse
注意: 如果数组双端队列为空,则peek(),peekFirst()和getLast()会引发NoSuchElementException。
移除ArrayDeque中的元素 移除元素remove()、removeFirst()、removeLast()
remove() - 返回并从数组双端队列的第一个元素中删除一个元素.
removeFirst() - 返回并从数组双端队列中删除第一个元素(与remove()等效)
remove(element) - 返回并从数组双端队列的头部移除指定的元素
removeLast() - 返回并从数组双端队列中删除最后一个元素
注意: 如果数组双端队列为空,则remove(),removeFirst()和removeLast()方法将引发异常。另外,如果未找到元素,则remove(element)会引发异常。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.remove(); System.out.println("Removed Element: " + element); System.out.println("New ArrayDeque: " + animals); String firstElement = animals.removeFirst(); System.out.println("Removed First Element: " + firstElement); String lastElement = animals.removeLast(); System.out.println("Removed Last Element: " + lastElement); } }
输出:
1 2 3 4 5 ArrayDeque: [Dog, Cat, Cow, Horse] Removed Element: Dog New ArrayDeque: [Cat, Cow, Horse] Removed First Element: Cat Removed Last Element: Horse
移除元素poll()、pollFirst()、pollLast()方法
poll() - 返回并删除数组双端队列的第一个元素
pollFirst() - 返回并删除数组双端队列的第一个元素(与poll()等效)
pollLast() - 返回并删除数组双端队列的最后一个元素
注意: 如果数组双端队列为空,则如果找不到该元素,则poll(),pollFirst()和pollLast()返回null。
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Cow" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); String element = animals.poll(); System.out.println("Removed Element: " + element); System.out.println("New ArrayDeque: " + animals); String firstElement = animals.pollFirst(); System.out.println("Removed First Element: " + firstElement); String lastElement = animals.pollLast(); System.out.println("Removed Last Element: " + lastElement); } }
输出:
1 2 3 4 5 ArrayDeque: [Dog, Cat, Cow, Horse] Removed Element: Dog New ArrayDeque: [Cat, Cow, Horse] Removed First Element: Cat Removed Last Element: Horse
移除所有元素clear() 要从数组双端队列中删除所有元素,我们使用clear()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayDeque: " + animals); animals.clear(); System.out.println("New ArrayDeque: " + animals); } }
输出:
1 2 ArrayDeque: [Dog, Cat, Horse] New ArrayDeque: []
遍历 ArrayDeque
iterator() - 返回一个迭代器,该迭代器可用于遍历数组双端队列
descendingIterator() - 返回一个迭代器,该迭代器可用于以相反顺序遍历数组双端队列
为了使用这些方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.ArrayDeque;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayDeque<String> animals= new ArrayDeque<>(); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.print("ArrayDeque: " ); Iterator<String> iterate = animals.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } System.out.print("\nArrayDeque in reverse order: " ); Iterator<String> desIterate = animals.descendingIterator(); while (desIterate.hasNext()) { System.out.print(desIterate.next()); System.out.print(", " ); } } }
输出:
1 2 ArrayDeque: [Dog, Cat, Horse] ArrayDeque in reverse order: [Horse, Cat, Dog]
其他方法
Methods
Descriptions
element()
从数组双端队列的头部返回一个元素。
contains(element)
在数组双端队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size()
返回数组双端队列的长度。
toArray()
将数组双端队列转换为数组并返回。
clone()
创建数组双端队列的副本并返回它。
ArrayDeque作为栈(Stack) 要在Java中实现LIFO(后进先出)堆栈,建议使用deque。ArrayDeque会比Stack更快些.
ArrayDeque提供了以下可用于实现stack的方法。
push - 添加一个元素到stack顶部
peek -返回stack顶部的元素
pop()- 移除并返回stack顶部的元素
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayDeque;class Main { public static void main (String[] args) { ArrayDeque<String> stack = new ArrayDeque<>(); stack.push("Dog" ); stack.push("Cat" ); stack.push("Horse" ); System.out.println("Stack: " + stack); String element = stack.peek(); System.out.println("Accessed Element: " + element); String remElement = stack.pop(); System.out.println("Removed element: " + remElement); } }
输出:
1 2 3 Stack: [Horse, Cat, Dog] Accessed Element: Horse Removed Element: Horse
ArrayDequeVsLinkedList ClassArrayDeque和Java LinkedList均实现Deque接口。但是他们存在一些差别
LinkedList 支持null元素,但是ArrayDeque不支持
链表中的每个节点都包含指向其他节点的链接。这就是为什么LinkedList比ArrayDeque需要更多存储的原因。
如果要实现队列或双端队列数据结构,ArrayDeque可能比LinkedList更快。
BlockingQueue接口扩展了Queue接口.它允许任何操作等待成功执行。
例如,如果我们要从空队列中删除元素,则blcoking queue允许删除操作等待,直到队列中包含一些要删除的元素。
实现BlockingQueue 由于BlockingQueue是一个接口,因此我们无法提供它的直接实现。为了使用BlockingQueue的功能,我们需要使用实现它的类。
如何使用blocking queues 为了使用BlockingQueue,我们必须导入java.util.concurrent.BlockingQueue包。
1 2 3 4 5 BlockingQueue<String> animal1 = new ArraryBlockingQueue<>(); BlockingQueue<String> animal2 = new LinkedBlockingQueue<>();
在这里,我们分别创建了类ArrayBlockingQueue和LinkedBlockingQueue的对象animal1和animal2。这些对象可以使用BlockingQueue接口的功能。
BlockingQueue方法 根据队列是满还是空,阻塞队列的方法可以分为3类:
这些方法会抛出异常
add() - 将元素插入到队列末尾的blocking queue队列中。如果队列以满,则抛出异常
element() - 返回blocking queue头部元素.如果队列为空则抛出异常
remove() - 从blocking queue移除元素.如果队列为空则抛出异常.
返回一些值的方法
offer() - 将元素插入到blocking queue队列的尾部.如果队列已满,则返回false.
peek() - 返回blocking queue队列头部元素.如果队列为空则返回null.
poll() - 从blocking queue队列删除一个元素. 如果队列为空,则返回null.
offer()和poll()更多信息offer()和poll()方法可以设定时间。也就是说,我们可以传递时间单位作为参数。例如:
1 offer(value, 100 , milliseconds)
value - 需要插入到队列的数据
100-延迟时间
milliseconds - 时间单位
这意味着offer()方法将尝试将元素插入block queue用100毫秒。如果无法在100毫秒内插入元素,则该方法返回false。
注意: 除了milliseconds我们还可以配置:days,hours,minutes,seconds,microseconds,nanoseconds用于offer()和poll()方法.
blocks中的操作符 BlockingQueue提供了等待操作队列方法,如果队列为空或者已满.
put() - 将元素插入到blocking queue。如果队列已满,它将等待直到队列有空间插入元素。
take() - 从blocking queue移除第一个元素并返回一个元素.如果队列为空,则等待队列有元素再删除.
假设我们想将元素插入队列。如果队列已满,则put()方法将等待,直到队列有空间插入元素。
同样,如果我们要从队列中删除元素。如果队列为空,则take()方法将等待直到队列包含要删除的元素。
ArrayBlockingQueue实现BlockingQueue1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.concurrent.BlockingQueue;import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(5 ); try { numbers.put(2 ); numbers.put(1 ); numbers.put(3 ); System.out.println("BLockingQueue: " + numbers); int removedNumber = numbers.take(); System.out.println("Removed Number: " + removedNumber); } catch (Exception e) { e.getStackTrace(); } } }
输出:
1 2 BlockingQueue: [2 , 1 , 3 ] Removed Element: 2
为什么使用BlockingQueue 在Java中,BlockingQueue被视为线程安全的集合。这是因为它在多线程操作中可能会有所帮助。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程运行较慢,则阻塞队列可使第二个线程等待,直到第一个线程完成其操作。
ArrayBlockingQueue实现了Java Collections框架中blocking queue接口通过数组.
创建ArrayBlockingQueue 创建一个数组blocking queue,我们必须导入java.util.concurrent.ArrayBlockingQueue包.
导入包后,可以使用以下方法在Java中创建数组blocking queue:
1 ArrayBlockingQueue<Type> animal = new ArrayBlockingQueue<>(int capacity);
Type - array blocking queue的类型
capacity - 这个 array blocking queue大小
1 2 3 4 5 ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); ArrayBlockingQueue<Integer> age = new ArrayBlockingQueue<>(5 );
注意: 必须提供数组的大小.
ArrayBlockingQueue中方法ArrayBlockingQueue类提供BlockingQueue接口中所有方法的实现。
这些方法用于从数组blocking queue中插入,访问和删除元素。
put()和take()方法支持blocking操作在array blocking queue.
这个两个方法会和array blocking queue其他类型队列有区别.
插入元素
add() - 将指定的元素插入到array blocking queue.如果队列满了则抛出异常.
offer() - 将指定的元素插入到array blocking queue.如果队列满了则返回false.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.offer("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); } }
输出:
1 ArrayBlockingQueue: [Dog, Cat, Horse]
获取元素
peek() - 从array blocking queue头部返回一个元素.如果队列是空则返回null
iterator() - 返回一个迭代器对象,以顺序访问array blocking queue中的元素。如果队列为空,则抛出异常。我们必须导入java.util.Iterator包才能使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.concurrent.ArrayBlockingQueue;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); String element = animals.peek(); System.out.println("Accessed Element: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("ArrayBlockingQueue Elements: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 3 ArrayBlockingQueue: [Dog, Cat, Horse] Accessed Element: Dog ArrayBlockingQueue Elements: Dog, Cat, Horse,
移除元素
remove() - 移除并返回删除的制定元素从array blocking queue.如果队列为空则抛出异常.
poll() - 移除并返回删除的制定元素从array blocking queue.如果队列为空则返回null
clear() - 从array block queue所有元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("ArrayBlockingQueue: " + animals); String element1 = animals.remove(); System.out.println("Removed Element:" ); System.out.println("Using remove(): " + element1); String element2 = animals.poll(); System.out.println("Using poll(): " + element2); animals.clear(); System.out.println("Updated ArrayBlockingQueue: " + animals); } }
输入:
1 2 3 4 5 ArrayBlockingQueue: [Dog, Cat, Horse] Removed Elements: Using remove () : Dog Using poll () : Cat Updated ArrayBlockingQueue: []
put()和take()方法在多线程处理中,我们可以使用put()和take()阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。
put()方法将元素添加到array blocking queue尾部.
如果array blocking queue已满,它将等待,直到array blocking queue中有空间可添加元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("ArrayBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 ArrayBlockingQueue: [Dog, Cat]
在这里,如果put()方法在等待时被中断,则可能会抛出InterruptedException。因此,我们必须将其包含在try..catch块中。
take()方法删除array blocking queue中头部元素,并返回.
如果array blocking queue为空, 则等到array blocking queue有元素可以删除.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.concurrent.ArrayBlockingQueue;class Main { public static void main (String[] args) { ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("ArrayBlockingQueue: " + animals); String element = animals.take(); System.out.println("Removed Element: " + element); } catch (Exception e) { System.out.println(e); } } }
输出:
1 2 ArrayBlockingQueue: [Dog, Cat] Removed Element: Dog
在这里,如果take()方法在等待时被中断,则会抛出InterrupedException。因此,我们必须将其封闭在try ... catch块中。
其它方法
Methods
Descriptions
contains(element)
在array blocking queue搜索指定的元素.如果找到元素就返回true,没有找到则返回false.
size()
返回数组的长度
toArray()
转换array blocking queue为数组
toString()
转换array blocking queue为字符串
为啥使用ArrayBlockingQueue ArrayBlockingQueue使用数组作为其内部存储。
它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程比第二个线程慢,那么数组阻塞队列可以使第二个线程等待,直到第一个线程完成其操作。
Java Collections框架中的LinkedBlockingQueue实现了阻塞队列,实现了linked list接口.
创建LinkedBlockingQueue 为了创建linked blocking queue我们必须导入java.util.concurrent.LinkedBlockingQueue包.
不指定大小 1 LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>();
此处的默认初始容量为231-1。
指定大小 1 LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>(int capacity);
Type - linked blocking queue的类型
capacity - linked blocking queue的大小
1 2 3 4 5 LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); LinkedBlockingQueue<Integer> age = new LinkedBlockingQueue<>(5 );
注意:不必提供链接列表的大小。
LinkedBlockingQueue中的方法 LinkedBlockingQueue类提供BlockingQueue接口中所有方法的实现。
这些方法提供了LinkedBlockingQueue中插入,获取,删除元素的方法.
另外,我们还将学习支持LinkedBlockingQueue中的阻塞操作的两种方法put()和take()。
这两种方法将LinkedBlockingQueue与其他典型队列区分开来。
插入元素
add() - 将指定的元素插入到LinkedBlockingQueue中. 如果队列满了则它会抛出异常.
offer() - 将指定的元素插入到LinkedBlockingQueue中.如果队列满了则它会返回false.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.offer("Horse" ); System.out.println("LinkedBlockingQueue: " + animals); } }
输出:
1 LinkedBlockingQueue: [Dog, Cat, Horse]
获取元素
peek() - 将LinkedBlockingQueue中的第一个元素返回.如果队列为空,则返回null
iterator - 返回LinkedBlockQueue元素的迭代器.如果队列为空则它会抛出一个错误.使用它我们需要引入java.util.Iterator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.concurrent.LinkedBlockingQueue;import java.util.Iterator;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("LinkedBlockingQueue: " + animals); String element = animals.peek(); System.out.println("Accessed Element: " + element); Iterator<String> iterate = animals.iterator(); System.out.print("LinkedBlockingQueue Elements: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 3 LinkedBlockingQueue: [Dog, Cat, Horse] Accessed Element: Dog LinkedBlockingQueue Elements: Dog, Cat, Horse,
移除元素
remove() - 返回并LinkedBlockingQueue中删除指定的元素。当前队列如果为空则抛出异常.
poll() - 删除并返回LinkedBlockQueue的元素.如果队列为空则返回null.
clear() - 移除LinkedBlockQueue中的所有元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); animals.add("Dog" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("LinkedBlockingQueue " + animals); String element1 = animals.remove(); System.out.println("Removed Element:" ); System.out.println("Using remove(): " + element1); String element2 = animals.poll(); System.out.println("Using poll(): " + element2); animals.clear(); System.out.println("Updated LinkedBlockingQueue " + animals); } }
输出:
1 2 3 4 5 LinkedBlockingQueue: [Dog, Cat, Horse] Removed Elements: Using remove () : Dog Using poll () : Cat Updated LinkedBlockingQueue: []
put()和take()方法在多线程处理中,我们可以使用put()和take()阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。
put()方法要将指定的元素插入到LinkedBlockingQueue的末尾,我们使用put()方法。
如果链接的队列已满,它将等待,直到链接的队列中有足够的空间来插入元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("LinkedBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 LinkedBlockingQueue: [Dog, Cat]
在这里,如果put()方法在等待时被中断,则可能会抛出InterruptedException。
take()方法移除并返回LinkedBlockingQueue头部元素.
如果LinkedBlockingQueue为空,它会等待LinkedBlockingQueue存在元素并将它删除.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.concurrent.LinkedBlockingQueue;class Main { public static void main (String[] args) { LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5 ); try { animals.put("Dog" ); animals.put("Cat" ); System.out.println("LinkedBlockingQueue: " + animals); String element = animals.take(); System.out.println("Removed Element: " + element); System.out.println("New LinkedBlockingQueue: " + animals); } catch (Exception e) { System.out.println(e); } } }
输出:
1 2 3 LinkedBlockingQueue: [Dog, Cat] Removed Element: Dog New LinkedBlockingQueue: [Cat]
在这里,如果take()方法在等待时被中断,则会抛出InterrupedException。因此,我们必须将其封闭在try ... catch块中。
其它方法
Methods
Descriptions
contains(element)
在LinkedBlockingQueue搜索是否存在指定元素 . 如果找到则返回true,否则返回false.
size()
返回LinkedBlockingQueue的大小
toArray()
将LinkedBlockingQueue转换成数组
toString()
将LinkedBlockingQueue转换成字符串
为什么使用LinkedBlockingQueue LinkedBlockingQueue使用链接列表作为其内部存储。
它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。
假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。
现在,如果第一个线程比第二个线程慢,然后LinkedBlockingQueue可以使第二个线程等待,直到第一个线程完成其操作。
##Map 接口
Java collections framework 的Map接口提供了map数据结构的功能。
Working of Map Java中,元素在Map中以key/value形式保存着。Keys是与Values关联的唯一值。
一个map中不会包含重复的keys,每一个key都有关联的唯一一个value
我们可以使用与它们关联的键来访问和修改值。
在上图中,key/value有:us/United States、br/Brazil、es/Spain.
我们可以使用它们的对应键访问这些值。
注意: Map界面维护3个不同的集合:
keys集合
values集合
key/value关联值集合
我们可以分别访问:keys、values、key/value
实现Map 由于Map是interface,因此我们无法从中创建对象。
为了使用Map接口的功能,我们可以使用以下类:
这些类在集合框架中定义并实现Map接口。
扩展 Map 接口 这些子接口还扩展了Map接口:
怎样使用 Map 在Java中,必须导入java.util.Map包才能使用Map。
1 2 Map<Key, Value> numbers = new HashMap<>();
在上面的代码中,我们创建了一个名为numbers的Map。我们已经使用HashMap类来实现Map接口。
Key - 用于关联map中每个元素(值)的唯一标识符.
Value - map中key关联的元素
Map 中常用方法 Map接口包含Collection接口的所有方法。这是因为Collection是Map的超级接口。
除了Collection中可用的方法外,Map还包括以下方法:
put(K, V) - 将key-K和value-V插入到map中,如果key已经存在,则V替换旧值
putAll()- 将指定map中所有内容插入到当前map中
putIfAbsent(K, V) - 如果K与V并没有关联,则将它们插入到map中
get(K) - 返回与指定keyK关联的值。如果找不到该K,则返回null
getOrDefault(K, defaultValue) - 返回与指定keyK关联的值,如果key不存在,则返回defaultValue
containsKey(K) - 检查map中是否存在指定的keyK
containsValue(V) - 检查map中是否存在指定的valueV
replace(K,V) - 用新的valueV替换,keyK中旧的value
replace(K, oldValue, newValue) - 仅当keyK与valueoldValue关联时,才用新valuenewValue替换keyK的值
remove(K) - 从map中删除key是K中的数据
remove(K, V) - 从map中删除key是K,value是V的数据
keySet() - 返回map中所有key的集合
values() - 返回map中所有value的集合
entrySet() - 返回map中key/value集合
实现Map接口 HashMap 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.Map;import java.util.HashMap;class Main { public static void main (String[] args) { Map<String, Integer> numbers = new HashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); System.out.println("Map: " + numbers); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); System.out.println("Entries: " + numbers.entrySet()); int value = numbers.remove("Two" ); System.out.println("Removed Value: " + value); } }
输出:
1 2 3 4 5 Map: {One=1 , Two=2 } Keys: [One, Two] Values: [1 , 2 ] Entries: [One=1 , Two=2 ] Removed Value: 2
TreeMap 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.Map;import java.util.TreeMap;class Main { public static void main (String[] args) { Map<String, Integer> values = new TreeMap<>(); values.put("Second" , 2 ); values.put("First" , 1 ); System.out.println("Map using TreeMap: " + values); values.replace("First" , 11 ); values.replace("Second" , 22 ); System.out.println("New Map: " + values); int removedValue = values.remove("First" ); System.out.println("Removed Value: " + removedValue); } }
输出:
1 2 3 Map using TreeMap: {First=1 , Second=2 } New Map: {First=11 , Second=22 } Removed Value: 11
Java collections framework中HashMap类提供了 哈希表数据结构 功能
它将元素存储在key/value对中。此处,key是用于关联map上每个value的唯一标识符。
HashMap类实现Map接口
创建 HashMap 为了创建HashMap,我们必须首先导入java.util.HashMap包。导入包后,就可以使用Java创建HashMap。
1 2 HashMap<K, V> numbers = new HashMap<>();
在上面代码中,我们创建了名为numbers的hashmap.K代表key,V代表value.
1 HashMap<String, Integer> numbers = new HashMap<>();
上面例子中keys类型是String,values类型是Integer.
例子🌰 创建HashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> languages = new HashMap<>(); languages.put("Java" , 8 ); languages.put("JavaScript" , 1 ); languages.put("Python" , 3 ); System.out.println("HashMap: " + languages); } }
输出:
1 HashMap: {Java=8 , JavaScript=1 , Python=3 }
上面例子中我们创建了名为languages的HashMap.我们用put(k,v)向map中添加元素。
Java中HashMap 基本操作 HashMap中基本操作分为四种:
HashMap 中新增元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> numbers = new HashMap<>(); System.out.println("Initial HashMap: " + numbers); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("HashMap after put(): " + numbers); } }
输出:
1 2 Initial HashMap: {} HashMap after put () : {One=1 , Two=2 , Three=3 }
在上面的示例中,我们创建了一个名为number的HashMap。在这里,我们使用了put()方法将元素添加到数字中。
其他添加元素方法:
获取一个元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); String value = languages.get(1 ); System.out.println("Value at index 1: " + value); } }
输出:
1 2 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Value at index 1 : Java
上面例子中:
在这里,get()方法将key作为其参数,并返回与key关联的相应value。
通过keySet()、values()、entrySet()获取keys、values、key/value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); System.out.println("Keys: " + languages.keySet()); System.out.println("Values: " + languages.values()); System.out.println("Key/Value mappings: " + languages.entrySet()); } }
输出:
1 2 3 4 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Keys: [1 , 2 , 3 ] Values: [Java, Python, JavaScript] Key/Value mappings: [1 =Java, 2 =Python, 3 =JavaScript]
其他获取数据方法:
改变 HashMap值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("Original HashMap: " + languages); languages.replace(2 , "C++" ); System.out.println("HashMap using replace(): " + languages); } }
输出:
1 2 Original HashMap: {1 =Java, 2 =Python, 3 =JavaScript} HashMap using replace () : {1 =Java, 2 =C++, 3 =JavaScript}
将key是2的值替换成了C++.
其他修改值方法:
移除HashMap元素 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); String value = languages.remove(2 ); System.out.println("Removed value: " + value); System.out.println("Updated HashMap: " + languages); } }
输出:
1 2 3 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Removed value: Python Updated HashMap: {1 =Java, 3 =JavaScript}
在这里,remove()方法将key作为其参数。然后,它返回与key关联的value并删除条目。
也可以在某中条件下删除数据
在此,只有key2与valueC ++关联时,remove()方法才会删除该条目。由于2与C ++没有关联,因此它不会删除该条目。
其他 HashMap方法
遍历 HashMap 遍历HashMap可以通过Java for-each loop .我们可以遍历:keys、values、key/value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import java.util.HashMap;import java.util.Map.Entry;class Main { public static void main (String[] args) { HashMap<Integer, String> languages = new HashMap<>(); languages.put(1 , "Java" ); languages.put(2 , "Python" ); languages.put(3 , "JavaScript" ); System.out.println("HashMap: " + languages); System.out.print("Keys: " ); for (Integer key : languages.keySet()) { System.out.print(key); System.out.print(", " ); } System.out.print("\nValues: " ); for (String value : languages.values()) { System.out.print(value); System.out.print(", " ); } System.out.print("\nEntries: " ); for (Entry<Integer, String> entry : languages.entrySet()) { System.out.print(entry); System.out.print(", " ); } } }
输出:
1 2 3 4 HashMap: {1 =Java, 2 =Python, 3 =JavaScript} Keys: 1 , 2 , 3 , Values: Java, Python, JavaScript, Entries: 1 =Java, 2 =Python, 3 =JavaScript,
请注意,我们在上面的示例中使用了Map.Entry.这是Map接口的嵌套类,该类返回map的视图(元素)。
为了使用此类,我们首先需要导入java.util.Map.Entry包。
从其它Map 创建HashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashMap;import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> evenNumbers = new TreeMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("TreeMap: " + evenNumbers); HashMap<String, Integer> numbers = new HashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("HashMap: " + numbers); } }
输出:
1 2 TreeMap: {Four=4 , Two=2 } HashMap: {Two=2 , Three=3 , Four=4 }
在上面的示例中,我们创建了一个名为evenNumbers的TreeMap。注意表达式:
1 numbers = new HashMap<>(evenNumbers)
在这里,我们使用TreeMap创建一个名为number的HashMap。
注意:创建HashMap时,我们可以包括可选参数:容量和负载系数。
1 HashMap<K, V> numbers = new HashMap<>(8 , 0.6f );
8(容量是 8) - 这意味着它可以存储8个条目。
0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
Javacollections framework中LinkedHashMap类提供了Map接口的哈希表和链表实现。
LinkedHashMap接口扩展了HashMap类,以将其条目存储在哈希表中。它在内部维护所有条目之间的双向链接列表,以对条目进行排序。
创建 LinkedHashMap 为了创建LinkedHashMap,我们必须首先导入java.util.LinkedHashMap包。
1 2 LinkedHashMap<Key, Value> numbers = new LinkedHashMap<>(8 , 0.6f );
在上面的代码中,我们创建了一个名为Numbers的LinkedHashMap。
Key - 用于关联map中每个元素(value)的唯一标识符
Value - map中按key所关联的元素
注意新的LinkedHashMap <>(8,0.6)部分。在这里,第一个参数是容量,第二个参数是负载系数。
8(容量是 8) - 这意味着它可以存储8个条目。
0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
注意: LinkedHashMap类还允许我们定义其条目的顺序。例如
1 2 LinkedHashMap<Key, Value> numbers2 = new LinkedHashMap<>(capacity, loadFactor, accessOrder);
在这里,accessOrder是一个布尔值。其默认值为false。在这种情况下,链接的哈希图中的条目将根据其插入顺序进行排序。
如果accessOrder为true,LinkedHashMap中的条目将按从最近访问的顺序排列。
创建 LinkedHashMap 从另外一个 Map 创建一个包含其他map所有元素的LinkedHashMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("LinkedHashMap1: " + evenNumbers); LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap2: " + numbers); } }
输出:
1 2 LinkedHashMap1: {Two=2 , Four=4 } LinkedHashMap2: {Two=2 , Four=4 , Three=3 }
LinkedHashMap中的方法 插入元素
put() - 将指定的key/value映射插入到映射中
putAll() -将指定map中的所有条目插入此map中
putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入到map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("Original LinkedHashMap: " + evenNumbers); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("Updated LinkedHashMap(): " + evenNumbers); LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("New LinkedHashMap: " + numbers); } }
输出:
1 2 3 Original LinkedHashMap: {Two=2 , Four=4 } Updated LinkedHashMap: {Two=2 , Four=4 , Six=6 } New LinkedHashMap: {One=1 , Two=2 , Four=4 , Six=6 }
获取元素
entrySet() - 获取map中key/value的集合
keySet() - 获取map中keys的集合
values() - 获取map中values的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 LinkedHashMap: {One=1 , Two=2 , Three=3 } Key/Value mappings: [One=1 , Two=2 , Three=3 ] Keys: [One, Two, Three] Values: [1 , 2 , 3 ]
get() - 返回与指定key关联的value。如果找不到该键,则返回null
getOrDefault() - 返回与指定key关联的value。 如果key没有找到则返回默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Returned Number: " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Returned Number: " + value2); } }
输出:
1 2 3 LinkedHashMap: {One=1 , Two=2 , Three=3 } Returned Number: 3 Returned Number: 5
移除 LinkedHashMap中的元素
remove(key) - 返回并从map中删除与指定key关联的条目
remove(key, value) - 当key与value匹配时才从map中删除,返回boolean值说明删除是否成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.LinkedHashMap;class Main { public static void main (String[] args) { LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("LinkedHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry Three removed? " + result); System.out.println("Updated LinkedHashMap: " + numbers); } }
输出:
1 2 3 4 LinkedHashMap: {One=1 , Two=2 , Three=3 } Removed value: 2 Is the entry {Three=3 } removed? True Updated LinkedHashMap: {One=1 }
LinkedHashMap中其他方法
Method
Description
clear()
从map上删除所有条目
containsKey()
检查map是否包含指定的key并返回布尔值
containsValue()
检查map是否包含指定的value并返回布尔值
size()
返回map大小
isEmpty()
检查map是否为空并返回布尔值
LinkedHashMap Vs. HashMap LinkedHashMap和HashMap都实现Map接口,但它们存在一些差别
LinkedHashMap在内部维护一个双向链接列表。因此,它保持其元素的插入顺序。
LinkedHashMap类比`HashMap需要更多的存储空间。这是因为LinkedHashMap在内部维护链接列表。
LinkedHashMap的性能比HashMap慢。
Java collections framework 中的WeakHashMap类提供了哈希表数据结构的功能。
注意:weak hashmap中key是 弱引用 类型
如果引用不再在程序中使用,则弱引用类型的对象可以在Java中被垃圾回收。
创建一个 WeakHashMap 为了创建一个weakHashMap,我们必须首先导入java.util.WeakHashMap包
1 2 WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8 , 0.6 );
在上面的代码中,我们创建了一个名为Numbers的WeakHashMap。
Key - 用于关联map中每个元素(value)的唯一标识符
Value - map中按key所关联的元素
注意新的LinkedHashMap <>(8,0.6)部分。在这里,第一个参数是容量,第二个参数是负载系数。
8(容量是 8) - 这意味着它可以存储8个条目。
0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.
如果未使用可选参数,则默认容量为16,默认负载系数为0.75。
HashMap 和 WeakHashMap 让我们看看Java中weak Hash Map的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; String four = new String("Four" ); Integer fourValue = 4 ; numbers.put(two, twoValue); numbers.put(four, fourValue); System.out.println("WeakHashMap: " + numbers); two = null ; System.gc(); System.out.println("WeakHashMap after garbage collection: " + numbers); } }
输出:
1 2 WeakHashMap: {Four=4 , Two=2 } WeakHashMap after garbage collection: {Four}
如我们所见,当weakHashMap中key是2设置为null并执行垃圾回收时,该键将被删除。
因为与hashMap不同,weakHashMap中的key是弱引用类型。这意味着,如果不再使用映射条目,则垃圾收集器将删除该条目。这对于节省资源很有用。
现在让我们在hashMap中查看相同的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> numbers = new HashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; String four = new String("Four" ); Integer fourValue = 4 ; numbers.put(two, twoValue); numbers.put(four, fourValue); System.out.println("HashMap: " + numbers); two = null ; System.gc(); System.out.println("HashMap after garbage collection: " + numbers); } }
输出:
1 2 HashMap: {Four=4 , Two=2 } HashMap after garbage collection: {Four=4 , Two=2 }
在这里,当hashMap的key是2设置为null并执行垃圾回收时,不会删除该键。
这是因为与weakHashMap不同,hashMap的key具有强引用类型。这意味着垃圾回收器不会删除映射的条目,即使不再使用该条目的键。
hashMap和weakHashMap的所有功能都相似,只是weakHashMap的键具有弱引用性,而hashMap的键具有强引用性。
创建一个 WeakHashMap从其它Map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashMap;import java.util.WeakHashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> evenNumbers = new HashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; evenNumbers.put(two, twoValue); System.out.println("HashMap: " + evenNumbers); WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers); System.out.println("WeakHashMap: " + numbers); } }
输出:
1 2 HashMap: {Two=2 } WeakHashMap: {Two=2 }
WeakHashMap中的方法 插入元素
put() - 将指定的key/value插入到map
putAll() - 将指定map中的所有条目插入此map中
putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入到map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>(); String two = new String("Two" ); Integer twoValue = 2 ; evenNumbers.put(two, twoValue); String four = new String("Four" ); Integer fourValue = 4 ; evenNumbers.putIfAbsent(four, fourValue); System.out.println("WeakHashMap of even numbers: " + evenNumbers); WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); numbers.putAll(evenNumbers); System.out.println("WeakHashMap of numbers: " + numbers); } }
输出:
1 2 WeakHashMap of even numbers: {Four=4 , Two=2 } WeakHashMap of numbers: {Two=2 , Four=4 , One=1 }
获取元素
entrySet() - 获取map中key/value的集合
keySet() - 获取map中keys的集合
values() - 获取map中values的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 WeakHashMap: {Two=2 , One=1 } Key/Value mappings: [Two=2 , One=1 ] Keys: [Two, One] Values: [1 , 2 ]
get() - 返回与指定key关联的value。如果找不到该键,则返回null
getOrDefault() - 返回与指定key关联的value。 如果key没有找到则返回默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); int value1 = numbers.get("Two" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Four" , 4 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 WeakHashMap: {Two=2 , One=1 } Using get () : 2 Using getOrDefault () : 4
移除元素
remove(key) - 返回并从map中删除与指定key关联的条目
remove(key, value) - 当key与value匹配时才从map中删除,返回boolean值说明删除是否成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.WeakHashMap;class Main { public static void main (String[] args) { WeakHashMap<String, Integer> numbers = new WeakHashMap<>(); String one = new String("One" ); Integer oneValue = 1 ; numbers.put(one, oneValue); String two = new String("Two" ); Integer twoValue = 2 ; numbers.put(two, twoValue); System.out.println("WeakHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("One" , 3 ); System.out.println("Is the entry {One=3} removed? " + result); System.out.println("Updated WeakHashMap: " + numbers); } }
输出:
1 2 3 4 WeakHashMap: {Two=2 , One=1 } Removed value: 2 Is the entry {One=3 } removed? False Updated WeakHashMap: {One=1 }
WeakHashMap中其他方法
Method
Description
clear()
从map上删除所有条目
containsKey()
检查map是否包含指定的key并返回布尔值
containsValue()
检查map是否包含指定的value并返回布尔值
size()
返回map大小
isEmpty()
检查map是否为空并返回布尔值
java collections framework的EnumMap提供了在Map中实现枚举的能力。
在EnumMap中,枚举元素用作keys,它实现了Map接口。
创建一个 EnumMap 为了创建一个EnumMap,我们必须首先导入java.util.EnumMap包。
1 2 3 4 5 enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
在上面的示例中,我们创建了一个名为size的EnumMap。
Size - map中的keys枚举值
Integer - 与keys相关联的value值
EnumMap中的方法 插入元素
put() - 将key/value插入到EnumMap 中
putAll() - 将指定的map数据全部插入到当前map中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes1 = new EnumMap<>(Size.class); sizes1.put(Size.SMALL, 28 ); sizes1.put(Size.MEDIUM, 32 ); System.out.println("EnumMap1: " + sizes1); EnumMap<Size, Integer> sizes2 = new EnumMap<>(Size.class); sizes2.putAll(sizes1); sizes2.put(Size.LARGE, 36 ); System.out.println("EnumMap2: " + sizes2); } }
输出:
1 2 EnumMap1: {SMALL=28 , MEDIUM=32 } EnumMap2: {SMALL=28 , MEDIUM=32 , LARGE=36 }
在上面的示例中,我们使用putAll()方法将enum map size1的所有元素插入到enum map size2的中。
enum map的putAll()还插入其他类型的map(HashMap、TreeMap).但是,所有map都应具有相同的枚举类型。
获取元素
entrySet() - 返回一个enum map的所有key/value映射(条目)的集合
keySet() - 返回一个enum map中所有的keys集合
values() - 返回一个enum map中所有的values集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); System.out.println("Key/Value mappings: " + sizes.entrySet()); System.out.println("Keys: " + sizes.keySet()); System.out.println("Values: " + sizes.values()); } }
输出:
1 2 3 4 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Key/Value mappings: [SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 ] Keys: [SMALL, MEDIUM, LARGE, EXTRALARGE] Values: [28 , 32 , 36 , 40 ]
get(key) - 指定的key返回value,如果key不存在则返回null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); int value = sizes.get(Size.MEDIUM); System.out.println("Value of MEDIUM: " + value); } }
输出:
1 2 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Value of MEDIUM: 32
移除元素
remove(key) - 根据key删除数据,如果删除成功则返回该数据
remove(key, value) - 当map中存在key/value匹配情况则删除,返回boolean类型值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); int value = sizes.remove(Size.MEDIUM); System.out.println("Removed Value: " + value); boolean result = sizes.remove(Size.SMALL, 28 ); System.out.println("Is the entry {SMALL=28} removed? " + result); System.out.println("Updated EnumMap: " + sizes); } }
输出:
1 2 3 4 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } Removed Value: 32 Is the entry {SMALL=28 } removed? True Updated EnumMap: {LARGE=36 , EXTRALARGE=40 }
替换元素
replace(key, value) - 将key对于的值替换成value
replace(key, old, new) - 如果key对于的值是old则替换成new
replaceAll(function) - 将map的每个值替换为指定函数的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.EnumMap;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class); sizes.put(Size.SMALL, 28 ); sizes.put(Size.MEDIUM, 32 ); sizes.put(Size.LARGE, 36 ); sizes.put(Size.EXTRALARGE, 40 ); System.out.println("EnumMap: " + sizes); sizes.replace(Size.MEDIUM, 30 ); sizes.replace(Size.LARGE, 36 , 34 ); System.out.println("EnumMap using replace(): " + sizes); sizes.replaceAll((key, oldValue) -> oldValue + 3 ); System.out.println("EnumMap using replaceAll(): " + sizes); } }
输出:
1 2 3 EnumMap: {SMALL=28 , MEDIUM=32 , LARGE=36 , EXTRALARGE=40 } EnumMap using replace () : {SMALL=28 , MEDIUM=30 , LARGE=34 , EXTRALARGE=40 }EnumMap using replaceAll () : {SMALL=31 , MEDIUM=33 , LARGE=37 , EXTRALARGE=43 }
EnumMap中其他方法
Method
Description
clone()
创建EnumMap的副本
containsKey()
在EnumMap中搜索指定的键,并返回一个布尔结果
containsValue()
在EnumMap中搜索指定的值,并返回一个布尔结果
size()
返回EnumMap的大小
clear()
从EnumMap中删除所有条目
EnumSet Vs. EnumMap EnumSet和EnumMap类都提供数据结构来存储枚举值。但是,它们之间存在一些主要差异。
EnumSet在内部以位序列表示,而EnumMap在内部以数组表示。
EnumSet是使用其预定义方法(例如allOf(),noneOf(),of()),但是,EnumMap是使用其构造函数创建的。
可克隆和可序列化的接口 EnumMap类还实现了Cloneable和Serializable接口。
Cloneable 它允许EnumMap类制作该类实例的副本。
Serializable 每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。
Serializable接口允许对类进行序列化。这意味着可以将实现Serializable的类的对象转换为位或字节。
Java collections framework的SortedMap接口可对存储在map中的key进行排序。
实现 SortedMap的类 由于SortedMap是一个接口,因此无法从中创建对象。
为了使用SortedMap接口的功能,我们需要使用实现该接口的类TreeMap。
怎么使用SortedMap 要使用SortedMap,我们必须首先导入java.util.SortedMap包。
1 2 SortedMap<Key, Value> numbers = new TreeMap<>();
key - 用于关联map中每个元素(值)的唯一标识符
Value-map中按key关联的元素
在这里,我们没有使用任何参数来创建排序的map,因此,map将自然排序(升序)。
SortedMap中的方法 SortedMap接口包含Map接口的所有方法。这是因为Map是SortedMap的超级接口。
除了所有这些方法之外,以下是SortedMap接口专用的方法。
comparator() -返回一个可用于对map中的key进行排序的比较器
firstKey() - 返回已排序映射的第一个key
lastKey() - 返回已排序映射的最后一个key
headMap(key) - 返回其key小于指定key的map的所有条目
tailMap(key) - 返回其key大于或等于指定键的映射的所有条目
subMap(key1, key2) - 返回其key位于key1和key2之间(包括key1)的map的所有条目
TreeMap实现SortedMap类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.SortedMap;import java.util.TreeMap;class Main { public static void main (String[] args) { SortedMap<String, Integer> numbers = new TreeMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); System.out.println("SortedMap: " + numbers); System.out.println("First Key: " + numbers.firstKey()); System.out.println("Last Key: " + numbers.lastKey()); int value = numbers.remove("One" ); System.out.println("Removed Value: " + value); } }
输出:
1 2 3 4 SortedMap: {One=1 , Two=2 } First Key: One Last Key: Two Removed Value: 1
Java collections framework的NavigableMap提供了 map中数据互相导航的能力
NavigableMap继承至SortedMap
实现NavigableMap的类 由于NavigableMap是一个接口,因此我们无法从中创建对象。
为了使用NavigableMap接口的功能,我们需要使用实现NavigableMap的TreeMap类。
怎么使用 NavigableMap 在Java中,我们必须导入java.util.NavigableMap包才能使用NavigableMap。
1 2 NavigableMap<Key, Value> numbers = new TreeMap<>();
在上面的代码中,我们创建了一个名为numbers的TreeMap类。
Key - 用于关联map中每个元素(值)的唯一标识符
Value - map中按key关联的元素
NavigableMap中的方法 NavigableMap被视为SortedMap的一种。这是因为NavigableMap扩展了SortedMap接口。因此,所有的SortedMap方法在NavigableMap中也可用。
但是,在NavigableMap中对SortedMap的某些方法(headMap(),tailMap()和subMap())进行了不同的定义。
headMap(key, booleanValue) headMap()会将navigable map中key之前所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true
如果booleanValue是true,表示该方法返回key之前的keys所有关联数据包括key本身
tailMap(key, booleanValue) tailMap()会将navigable map中key之后所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true
如果booleanValue是个false,则该方法返回key之后keys所有关联数据包括key本身
subMap(k1, bv1, k2, bv2) subMap()返回k1与k2之间所有的数据,包括k1数据
bv1和bv2是可选参数。 bv1的默认值为true,bv2的默认值为false
如果将bv1设为false,则返回k1与k2之间所有的数据,不包括k1数据
如果将bv2设为true,则返回k1与k2之间所有的数据,包括k2的数据
其它方法 NavigableMap提供了各种用于设置数据在map中位置的方法。
descendingMap()-反转map中的数据顺序
descendingKeyMap() - 反转map中keys的顺序
ceilingEntry() - 返回所有大于或等于指定key中,最小key关联的数据
ceilingKey() - 返回所有大于或等于指定key中,最小key
floorEntry() - 返回所有小于或等于指定key中,最大key关联的数据
floorKey() - 返回所有小于或等于指定key中,最大key
higherEntry() - 返回所有大于指定key中,最小key关联的数据
higherKey() - 返回所有大于指定key中,最小key
lowerEntry() - 返回所有小于指定key中,最大key关联的数据
lowerKey() - 返回所有小于指定key中,最大的key
firstEntry() - 返回map的第一个数据(具有最小key的数据)
lastEntry() - 返回map中最后一个数据(具有最大key的数据)
pollFirstEntry() - 返回并删除map中第一个数据
pollLastEntry() - 返回并删除map中最后一个数据
NavigableMap 的实现 TreeMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.NavigableMap;import java.util.TreeMap;class Main { public static void main (String[] args) { NavigableMap<String, Integer> numbers = new TreeMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); numbers.put("Three" , 3 ); System.out.println("NavigableMap: " + numbers); System.out.println("First Entry: " + numbers.firstEntry()); System.out.println("Last Entry: " + numbers.lastEntry()); System.out.println("Removed First Entry: " + numbers.pollFirstEntry()); System.out.println("Removed Last Entry: " + numbers.pollLastEntry()); } }
输出:
1 2 3 4 5 NavigableMap: {One=1 , Three=3 , Two=2 } First Entry: One=1 Last Entry: Two=2 Removed First Entry: One=1 Removed Last Entry: Two=2
Java collections framework提供了 tree数据结构的实现
创建 TreeMap 为了创建TreeMap,我们必须首先导入java.util.TreeMap包。
1 TreeMap<Key, Value> numbers = new TreeMap<>();
在上面的代码中,我们创建了一个名为Numbers的TreeMap,没有任何参数。在这种情况下,TreeMap中的元素会自然排序(升序)。但是,我们可以使用Comparator接口自定义元素的排序。
Key - 用于关联map中每个元素(值)的唯一标识符
Value - map中按key关联的元素
TreeMap 中的方法 插入元素
put() - 将指定的key/value插入到map中
putAll() - 将指定到map所有数据插入到当前map中
putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> evenNumbers = new TreeMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("TreeMap of even numbers: " + evenNumbers); TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("TreeMap of numbers: " + numbers); } }
输出:
1 2 TreeMap of even numbers: {Four=4 , Six=6 , Two=2 } TreeMap of numbers: {Four=4 , One=1 , Six=6 , Two=2 }
获取元素
entrySet() - 返回 treemap中所有key/value集合
keySet() - 返回treemap中所有key集合
values() - 返回treemap中所有value集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 TreeMap: {One=1 , Three=3 , Two=2 } Key/Value mappings: [One=1 , Three=3 , Two=2 ] Keys: [One, Three, Two] Values: [1 , 3 , 2 ]
get(key) - 返回与指定key关联的value。如果找不到key,则返回null。
getOrDefault(key,defalutValue) - 返回与指定key关联的value。如果找不到key,则返回指定的默认值(defalutValue)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 TreeMap: {One=1 , Three=3 , Two=2 } Using get () : 3 Using getOrDefault () : 5
移除元素
remove(key) - 返回并从TreeMap中删除与指定key关联的数据
remove(key, value) - 仅当指定key与指定value相关联时才从map中删除数据,并返回布尔值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("TreeMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry {Three=3} removed? " + result); System.out.println("Updated TreeMap: " + numbers); } }
输出:
1 2 3 4 TreeMap: {One=1 , Three=3 , Two=2 } Removed value = 2 Is the entry {Three=3 } removed? True Updated TreeMap: {One=1 }
替换元素
replace(key, value) - 用新值value替换key关联的旧值
replace(key, old, new) -仅当旧值已与指定key关联时,才用新值替换旧值
replaceAll(function) - 将map的每个value替换为指定函数的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("Original TreeMap: " + numbers); numbers.replace("Second" , 22 ); numbers.replace("Third" , 3 , 33 ); System.out.println("TreeMap using replace: " + numbers); numbers.replaceAll((key, oldValue) -> oldValue + 2 ); System.out.println("TreeMap using replaceAll: " + numbers); } }
输出:
1 2 3 Original TreeMap: {First=1 , Second=2 , Third=3 } TreeMap using replace () : {First=1 , Second=22 , Third=33 }TreeMap using replaceAll () : {First=3 , Second=24 , Third=35 }
Navigation 中的方法 由于TreeMap类实现了NavigableMap,因此它提供了各种方法来浏览treemap的元素。
First and Last Methods
firstKey() - 返回 map 第一个key
firstEntry() - 返回map 第一个key 的数据(key/value)
lastKey() - 返回map最后一个key
lastEntry() - 返回map最后一个key的数据(key/value)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("TreeMap: " + numbers); String firstKey = numbers.firstKey(); System.out.println("First Key: " + firstKey); String lastKey = numbers.lastKey(); System.out.println("Last Key: " + lastKey); System.out.println("First Entry: " + numbers.firstEntry()); System.out.println("Last Entry: " + numbers.lastEntry()); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Second=2 , Third=3 } First Key: First Last Key: Third First Entry: First=1 Last Entry: Third=3
Ceiling、Floor、Higher and Lower Methods
ceilingEntry() - 返回所有大于或等于指定key中,最小key关联的数据
ceilingKey() - 返回所有大于或等于指定key中,最小key
floorEntry() - 返回所有小于或等于指定key中,最大key关联的数据
floorKey() - 返回所有小于或等于指定key中,最大key
higherEntry() - 返回所有大于指定key中,最小key关联的数据
higherKey() - 返回所有大于指定key中,最小key
lowerEntry() - 返回所有小于指定key中,最大key关联的数据
lowerKey() - 返回所有小于指定key中,最大的key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 5 ); numbers.put("Third" , 4 ); numbers.put("Fourth" , 6 ); System.out.println("TreeMap: " + numbers); System.out.println("Using higherKey(): " + numbers.higherKey("Fourth" )); System.out.println("Using higherEntry(): " + numbers.higherEntry("Fourth" )); System.out.println("\nUsing lowerKey(): " + numbers.lowerKey("Fourth" )); System.out.println("Using lowerEntry(): " + numbers.lowerEntry("Fourth" )); System.out.println("\nUsing ceilingKey(): " + numbers.ceilingKey("Fourth" )); System.out.println("Using ceilingEntry(): " + numbers.ceilingEntry("Fourth" )); System.out.println("\nUsing floorKey(): " + numbers.floorKey("Fourth" )); System.out.println("Using floorEntry(): " + numbers.floorEntry("Fourth" )); } }
输出:
1 2 3 4 5 6 7 8 9 10 11 12 TreeMap: {First=1 , Fourth=6 , Second=5 , Third=4 } Using higherKey () : Second Using higherEntry () : Second =5 Using lowerKey () : First Using lowerEntry () : First =1 Using ceilingKey () : Fourth Using ceilingEntry () : Fourth =6 Using floorkey () : Fourth Using floorEntry () : Fourth =6
pollFirstEntry() and pollLastEntry() Methods
pollFirstEntry() - 返回并删除map中第一个数据
pollLastEntry() - 返回并删除map中最后一个数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); System.out.println("TreeMap: " + numbers); System.out.println("Using pollFirstEntry(): " + numbers.pollFirstEntry()); System.out.println("Using pollLastEntry(): " + numbers.pollLastEntry()); System.out.println("Updated TreeMap: " + numbers); } }
输出:
1 2 3 4 TreeMap: {First=1 , Second=2 , Third=3 } Using pollFirstEntry () : First =1 Using pollLastEntry () : Third =3 Updated TreeMap: {Second=2 }
headMap(), tailMap() and subMap() Methods headMap(key,booleanValue)
headMap()会将treemap中key之前所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true
如果booleanValue是true,表示该方法返回key之前的keys所有关联数据包括key本身
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing headMap() Method:" ); System.out.println("Without boolean value: " + numbers.headMap("Fourth" )); System.out.println("With boolean value: " + numbers.headMap("Fourth" , true )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=4 , Second=2 , Third=3 } Using headMap () Method: Without boolean value: {First=1 }With boolean value: {First=1 , Fourth=4 }
tailMap(key, booleanValue)
tailMap()会将treemap中key之后所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true
如果booleanValue是个false,则该方法返回key之后keys所有关联数据包括key本身
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing tailMap() Method:" ); System.out.println("Without boolean value: " + numbers.tailMap("Second" )); System.out.println("With boolean value: " + numbers.tailMap("Second" , false )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=4 , Second=2 , Third=3 } Using tailMap () Method: Without boolean value: {Second=2 , Third=3 }With boolean value: {Third=3 }
subMap(k1, bV1, k2, bV2)
subMap()返回k1与k2之间所有的数据,包括k1数据
bv1和bv2是可选参数。 bv1的默认值为true,bv2的默认值为false
如果将bv1设为false,则返回k1与k2之间所有的数据,不包括k1数据
如果将bv2设为true,则返回k1与k2之间所有的数据,包括k2的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeMap;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); System.out.println("\nUsing subMap() Method:" ); System.out.println("Without boolean value: " + numbers.subMap("Fourth" , "Third" )); System.out.println("With boolean value: " + numbers.subMap("Fourth" , false , "Third" , true )); } }
输出:
1 2 3 4 5 TreeMap: {First=1 , Fourth=2 , Second=2 , Third=3 } Using subMap () Method: Without boolean value: {Fourth=4 , Second=2 }With boolean value: {Second=2 , Third=3 }
其它方法
Method
Description
clone()
创建TreeMap的副本
containsKey()
在TreeMap中搜索指定的key,并返回布尔结果
containsValue()
在TreeMap中搜索指定的value并返回布尔结果
size()
返回TreeMap的大小
clear()
从TreeMap中删除所有条目
TreeMap Comparator treemap元素默认是自然排序(以升序排列)。但是,我们也可以自定义key的顺序。
为此,我们需要基于treemap中的key排序来创建自己的比较器类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.TreeMap;import java.util.Comparator;class Main { public static void main (String[] args) { TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator()); numbers.put("First" , 1 ); numbers.put("Second" , 2 ); numbers.put("Third" , 3 ); numbers.put("Fourth" , 4 ); System.out.println("TreeMap: " + numbers); } public static class CustomComparator implements Comparator <String > { @Override public int compare (String number1, String number2) { int value = number1.compareTo(number2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } } }
输出:
1 TreeMap: {Third=3 , Second=2 , Fourth=4 , First=1 }
在上面的示例中,我们创建了一个treemap,将CustomComparator类作为参数传递。
CustomComparator类实现Comparator 接口。
然后,我们重写compare()方法,以相反的顺序对元素进行排序。
Java collections framework 的concurrentMap提供线程安全的map.也就是说,多个线程可以一次访问map,而不会影响映射中条目的一致性。
concurrentMap被称为同步map。
实现concurrentMap的 class concurrentMap是个接口,我们不能通过它创建对象。
如果我们想使用concurrentMap中的方法,我们需要使用concurrentHashMap类,它是concurrentMap的实现。
怎样使用 concurrentMap 要使用ConcurrentMap,我们必须首先导入java.util.concurrent.ConcurrentMap包。导入包后,将按照以下方法创建concurrentMap。
1 2 ConcurrentMap<Key, Value> numbers = new ConcurrentHashMap<>();
在上面的代码中,我们创建了一个名为Numbers的concurrentMap。
Key - 用于关联map每个元素(value)的唯一标识符.
Value - map中按key关联的元素.
concurrentMap中的方法 ConcurrentMap接口包含Map接口的所有方法。这是因为Map是ConcurrentMap接口的超级接口。
除了所有这些方法外,以下是ConcurrentMap接口特定的方法。
putIfAbsent() - 如果指定的key/value尚未与任何值关联,则将其插入到map中。
compute() - 计算指定key的数据及其它之前的value。
computeIfAbsent() - 如果自定的key尚未于map中任何value有关联,则通过传入的函数计算一个value与其关联。
computeIfPresent() - 如果指定的key有关联的value,则计算一个新的值。
forEach() - 访问map的所有条目并执行指定的操作。
merge() - 如果key已经映射到某个特定value,则将新的指定value与指定key的旧值合并。如果该key尚未映射,则该方法只需将指定的value与我们的key关联。
concurrentHashMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.ConcurrentMap;import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("Two" , 2 ); numbers.put("One" , 1 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentMap: " + numbers); int value = numbers.get("One" ); System.out.println("Accessed Value: " + value); int removedValue = numbers.remove("Two" ); System.out.println("Removed Value: " + removedValue); } }
输出:
1 2 3 ConcurrentMap: {One=1 , Two=2 , Three=3 } Accessed Value: 1 Removed Value: 2
Javacollections framework的concurrentHashMap类提供了线程安全的映射.也就是说,多个线程可以一次访问map,而不会影响map中数据的一致性。
创建concurrentHashMap 为了创建concurrentHashMao,我们必须首先导入java.util.concurrent.ConcurrentHashMap包。
1 2 ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8 , 0.6f );
Key - 用于关联map每个元素(value)的唯一标识符.
Value - map中按key关联的元素.
注意: ** ConcurrentHashMap <>(8,0.6)部分。在这里,第一个参数是 容量,第二个参数是 负载系数**。
capacity - 该map的容量为 8。意味着,它可以存储8条数据。
loadFactor - map的负载系数是 0.6。它意味着当 hash table填充 60%时,会新增原 hash table 两倍数据量数据添加到原 hash table中。
默认 capacity 和 loadFactor 创建 concurrent hashmap可以不定义 capacity 和 loadFactor.
1 2 ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();
capacity默认值是 16, loadFactor 默认值是 0.75.
通过另外的 map 创建 concurrentHashMap 这是我们如何创建包含其他映射的所有元素的concurrentHashMap。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.concurrent.ConcurrentHashMap;import java.util.HashMap;class Main { public static void main (String[] args) { HashMap<String, Integer> evenNumbers = new HashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); System.out.println("HashMap: " + evenNumbers); ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); } }
输出:
1 2 HashMap: {Four=4 , Two=2 } ConcurrentHashMap: {Four=4 , Two=2 , Three=3 }
concurrentHashMap 中的方法 插入元素
put() - 将指定的key/value数据插入到map中
putAll() - 将指定的map所有数据插入到当前map中
putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value插入到map中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>(); evenNumbers.put("Two" , 2 ); evenNumbers.put("Four" , 4 ); evenNumbers.putIfAbsent("Six" , 6 ); System.out.println("ConcurrentHashMap of even numbers: " + evenNumbers); ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.putAll(evenNumbers); System.out.println("ConcurrentHashMap of numbers: " + numbers); } }
输出:
1 2 ConcurrentHashMap of even numbers: {Six=6 , Four=4 , Two=2 } ConcurrentHashMap of numbers: {Six=6 , One=1 , Four=-4 , Two=2 }
获取元素
entrySet() - 返回map的所有key/value集合
keySet() - 返回map所有的key集合
valueSet() - 返回map所有的value集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); System.out.println("Key/Value mappings: " + numbers.entrySet()); System.out.println("Keys: " + numbers.keySet()); System.out.println("Values: " + numbers.values()); } }
输出:
1 2 3 4 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Key/Value mappings: [One=1 , Two=2 , Three=3 ] Keys: [One, Two, Three] Values: [1 , 2 , 3 ]
get() - 返回与指定key关联的value。如果找不到密钥,则返回null。
getOrDefault() - 返回与指定key关联的value。如果找不到密钥,则返回指定的默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int value1 = numbers.get("Three" ); System.out.println("Using get(): " + value1); int value2 = numbers.getOrDefault("Five" , 5 ); System.out.println("Using getOrDefault(): " + value2); } }
输出:
1 2 3 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Using get () : 3 Using getOrDefault () : 5
移除元素
remove(key) - 返回并从map中删除与指定key关联的数据
remove(key, value) - 仅在将指定key映射到指定value时在map中删除数据,并返回布尔值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int value = numbers.remove("Two" ); System.out.println("Removed value: " + value); boolean result = numbers.remove("Three" , 3 ); System.out.println("Is the entry {Three=3} removed? " + result); System.out.println("Updated ConcurrentHashMap: " + numbers); } }
输出:
1 2 3 4 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Removed value: 2 Is the entry {Three=3 } removed? True Updated ConcurrentHashMap: {One=1 }
批量操作 concurrentHashMap concurrentHashMap类提供了可以安全地应用于并发映射的不同批量操作。
forEach() 方法 forEach()方法遍历我们的数据目并执行指定的函数。它包含两个参数:
parallelismThreshold - 当数据量大于指定值时,进行并行计算。
transformer - 进行值处理的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); numbers.forEach(4 , (k, v) -> System.out.println("key: " + k + " value: " + v)); System.out.print("Values are " ); numbers.forEach(4 , (k, v) -> v, (v) -> System.out.print(v + ", " )); } }
输出:
1 2 3 4 5 ConcurrentHashMap: {One = 1 , Two = 2 , Three = 3 } key: One value: 1 key: Two value: 2 key: Three value: 3 Values are 1 , 2 , 3 ,
在上面的程序中,我们使用了并行阈值4。这意味着,如果map包含4个条目,则该操作将并行执行。
forEach() 变形方法
forEachEntry() - 为每个数据执行指定的功能
forEachKey() - 为每个key执行指定的功能
forEachValue() - 为每个value执行指定的函数
search() 方法 search() 方法基于指定的函数搜索map,并返回匹配的条目。
在此,指定的功能确定要搜索的条目。
它还包括一个可选参数parallelThreshold。并行阈值指定在map中有多少个元素之后并行执行该操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); String key = numbers.search(4 , (k, v) -> {return v == 3 ? k: null ;}); System.out.println("Searched value: " + key); } }
输出:
1 2 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Searched value: Three
search()的变形:
searchEntries() - 搜索功能应用于key/value映射
searchKeys() - 搜索功能仅适用于key
searchValues() - 搜索功能仅应用于value
reduce方法 reduce()方法累积(聚集)映射中的每条数据。当我们需要所有条数据来执行一项常见任务(例如添加地图的所有值)时,可以使用此方法。它有连个参数:
parallelismThreshold - 它指定在映射了几个元素之后,并行执行映射中的操作。
transformer - 进行数据处理的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.concurrent.ConcurrentHashMap;class Main { public static void main (String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One" , 1 ); numbers.put("Two" , 2 ); numbers.put("Three" , 3 ); System.out.println("ConcurrentHashMap: " + numbers); int sum = numbers.reduce(4 , (k, v) -> v, (v1, v2) -> v1 + v2); System.out.println("Sum of all values: " + sum); } }
输出:
1 2 ConcurrentHashMap: {One=1 , Two=2 , Three=3 } Sum of all values: 6
在上面的程序中,请注意以下语句:
1 numbers.reduce(4 , (k, v) -> v, (v1, v2) -> v1+v2);
4 - 并行阈值
(k,v) -> v是转换函数。它将key/value映射仅转换为value。
(v1, v2) -> v1+v2是一个累积函数。它收集所有value并添加所有值。
reduce()变形方法
reduceEntries() - 返回使用指定的reducer函数收集所有数据的结果
reduceKeys() - 返回使用指定的reducer函数收集所有key的结果
reduceValues() - 返回使用指定的reducer函数收集所有value的结果
ConcurrentHashMap vs HashMap 这是ConcurrentHashMap和HashMap之间的一些区别:
ConcurrentHashMap是线程安全的集合。也就是说,多个线程可以同时访问和修改它。
ConcurrentHashMap提供了用于批量操作的方法,例如forEach(),search()和reduce()
ConcurrentHashMap 优势
ConcurrentHashMap类允许多个线程同时访问数据。
默认情况下 concurrent hashmap是分为16段。这就是为什么允许16个线程同时并发修改映射的原因。但是,任何数量的线程一次都可以访问该map。
如果指定的key已经存在,则putIfAbsent()方法将不会覆盖映射中的数据。
它提供同步
Java collections framework的Set接口提供数学的集合 能力。它继承之collections接口。
与List接口不同,Set不能包含重复的元素。
实现Set接口的类 由于Set是接口,因此我们无法从中创建对象。
为了使用Set接口的功能,我们可以使用以下类:
继承Set的接口 这些子接口还扩展了Set接口:
怎么使用 Set 在Java中,我们必须导入java.util.Set包才能使用Set。
1 2 Set<String> animals = new HashSet<>();
在这里,我们创建了一个称为animals的Set。我们已经使用HashSet类实现Set接口。
Set中的方法 Set接口包含Collection接口的所有方法。
Set接口中还提供了Collection接口的一些常用方法:
add() - 将指定的元素添加到集合中
addAll() - 将指定集合的所有元素添加到集合中
iterator() - 返回一个迭代器,该迭代器可用于顺序访问集合中的元素
remove() - 从集合中移除指定的元素
removeAll() - 从存在于另一个指定集合中的集合中删除所有元素
retainAll() - 保留集合中也存在于另一个指定集合中的所有元素
clear() - 从集合中删除所有元素
size() - 返回集合的长度(元素数)
toArray() - 返回包含集合中所有元素的数组
contains() - 如果集合包含指定的元素,则返回true
containsAll() - 如果集合包含指定集合的所有元素,则返回true
hashCode() - 返回hash值(集合中元素的地址)
Set 操作符 Java Set接口允许我们执行基本的数学集合操作,例如并集,交集和子集。
Union - 要获得两个集合x和y的并集,我们可以使用x.addAll(y)
Intersection - 要获得两个集合x和y的交集,我们可以使用x.retainAll(y)
Subset - 要检查x是否是y的子集,我们可以使用y.containsAll(x)
Set接口的实现 HashSet 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.Set;import java.util.HashSet;class Main { public static void main (String[] args) { Set<Integer> set1 = new HashSet<>(); set1.add(2 ); set1.add(3 ); System.out.println("Set1: " + set1); Set<Integer> set2 = new HashSet<>(); set2.add(1 ); set2.add(2 ); System.out.println("Set2: " + set2); set2.addAll(set1); System.out.println("Union is: " + set2); } }
输出:
1 2 3 Set1: [2 , 3 ] Set2: [1 , 2 ] Union is: [1 , 2 , 3 ]
TreeSet 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.Set;import java.util.TreeSet;import java.util.Iterator;class Main { public static void main (String[] args) { Set<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(3 ); numbers.add(1 ); System.out.println("Set using TreeSet: " + numbers); System.out.print("Accessing elements using iterator(): " ); Iterator<Integer> iterate = numbers.iterator(); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 Set using TreeSet: [1 , 2 , 3 ] Accessing elements using iterator () : 1, 2, 3,
Java Collections framework 的HashSet类提供了hash table结构的功能。
创建 HashSet 为了创建hash set,我们必须首先导入java.util.HashSet包。
1 2 HashSet<Integer> numbers = new HashSet<>(8 , 0.75 );
注意,新的HashSet <>(8,0.75)部分。在这里,第一个参数是容量,第二个参数是负载系数。
capacity - 该hash st的容量为8。意味着,它可以存储8个元素。
loadFactor - 此hash set的负载系数为0.6。这意味着,只要我们的哈希集填充了60%,元素将移至新哈希表,其大小是原始哈希表的两倍。
默认 capacity 和 load factor 1 2 HashSet<Integer> numbers1 = new HashSet<>();
HashSet中的方法 插入元素
add() - 将指定的元素插入集合
addAll() - 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> evenNumber = new HashSet<>(); evenNumber.add(2 ); evenNumber.add(4 ); evenNumber.add(6 ); System.out.println("HashSet: " + evenNumber); HashSet<Integer> numbers = new HashSet<>(); numbers.addAll(evenNumber); numbers.add(5 ); System.out.println("New HashSet: " + numbers); } }
输出:
1 2 HashSet: [2 , 4 , 6 ] New HashSet: [2 , 4 , 5 , 6 ]
获取元素 要访问hashset的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;import java.util.Iterator;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("HashSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("HashSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 HashSet: [2 , 5 , 6 ] HashSet using Iterator: 2 , 5 , 6 ,
移除元素
remvoe() - 从set中移除指定的元素
removeAll() - 从set中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("HashSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 HashSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Set 操作符 HashSet类的各种方法也可以用于执行各种设置操作。
Union 操作 两个执行两个集合之间的联合,我们可以使用addAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> evenNumbers = new HashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("HashSet1: " + evenNumbers); HashSet<Integer> numbers = new HashSet<>(); numbers.add(1 ); numbers.add(3 ); System.out.println("HashSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 HashSet1: [2 , 4 ] HashSet2: [1 , 3 ] Union is: [1 , 2 , 3 , 4 ]
Intersection 操作 为了执行两个集合之间的交集,我们可以使用retainAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("HashSet1: " + primeNumbers); HashSet<Integer> evenNumbers = new HashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("HashSet2: " + evenNumbers); evenNumbers.retainAll(primeNumbers); System.out.println("Intersection is: " + evenNumbers); } }
输出:
1 2 3 HashSet1: [2 , 3 ] HashSet2: [2 , 4 ] Intersection is: [2 ]
Difference 操作 要计算两组之间的差异,我们可以使用removeAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); primeNumbers.add(5 ); System.out.println("HashSet1: " + primeNumbers); HashSet<Integer> oddNumbers = new HashSet<>(); oddNumbers.add(1 ); oddNumbers.add(3 ); oddNumbers.add(5 ); System.out.println("HashSet2: " + oddNumbers); primeNumbers.removeAll(oddNumbers); System.out.println("Difference : " + primeNumbers); } }
输出:
1 2 3 HashSet1: [2 , 3 , 5 ] HashSet2: [1 , 3 , 5 ] Difference: [2 ]
Subset 为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.HashSet;class Main { public static void main (String[] args) { HashSet<Integer> numbers = new HashSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("HashSet1: " + numbers); HashSet<Integer> primeNumbers = new HashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("HashSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is HashSet2 is subset of HashSet1? " + result); } }
输出:
1 2 3 HashSet1: [1 , 2 , 3 , 4 ] HashSet2: [2 , 3 ] Is HashSet2 is a subset of HashSet1? true
其它HashSet 方法
Method
Description
clone()
创建HashSet的副本
contains()
在HashSet中搜索指定的元素并返回布尔结果
isEmpty()
检查`HashSet是否为空
size()
返回HashSet的大小
clear()
从HashSet中删除所有元素
HashSet 好处 在Java中,如果我们必须随机访问元素,则通常使用HashSet。这是因为使用哈希码访问哈希表中的元素。
元素的hashcode是唯一的标识,有助于标识哈希表中的元素。
HashSet不能包含重复的元素。因此,每个哈希集元素都有一个唯一的哈希码。
注意:HashSet不同步。也就是说,如果多个线程同时访问哈希集,并且其中一个线程修改了哈希集。然后必须从外部进行同步
Javacollections framework的EnumSet类提供单个枚举元素的固定实现。
创建 EnumSet 为了创建一个枚举集,我们必须首先导入java.util.EnumSet包。
与其他集合实现不同,枚举集合没有公共构造函数。我们必须使用预定义的方法来创建一个枚举集。
allOf(Size) allof()方法创建一个枚举集,其中包含指定枚举类型Size的所有值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); System.out.println("EnumSet: " + sizes); } }
输出:
1 EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE]
注意:
1 EnumSet<Size> sizes = EnumSet.allOf(Size.class);
在这里,Size.class表示我们创建的Size枚举。
noneOf(size) noneOf()方法创建一个空的枚举集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.noneOf(Size.class); System.out.println("Empty EnumSet: " + sizes); } }
输出:
在这里,我们创建了一个空的枚举,名为sizes。
注意: 我们只能在上述程序中插入枚举类型为Size的元素。这是因为我们使用Size枚举创建了空的枚举集。
range(e1, e2) range()方法创建一个枚举集,其中包含e1和e2之间的枚举的所有值,包括两个值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.range(Size.MEDIUM, Size.EXTRALARGE); System.out.println("EnumSet: " + sizes); } }
输出:
1 EnumSet: [MEDIUM, LARGE, EXTRALARGE]
of() of()方法创建一个包含指定元素的枚举集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes1 = EnumSet.of(Size.MEDIUM); System.out.println("EnumSet1: " + sizes1); EnumSet<Size> sizes2 = EnumSet.of(Size.SMALL, Size.LARGE); System.out.println("EnumSet2: " + sizes2); } }
输出:
1 2 EnumSet1: [MEDIUM] EnumSet2: [SMALL, LARGE]
EnumSet 中方法 插入元素
add() - 将指定的枚举值插入到枚举集中
addAll() - 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes1 = EnumSet.allOf(Size.class); EnumSet<Size> sizes2 = EnumSet.noneOf(Size.class); sizes2.add(Size.MEDIUM); System.out.println("EnumSet Using add(): " + sizes2); sizes2.addAll(sizes1); System.out.println("EnumSet Using addAll(): " + sizes2); } }
输出:
1 2 EnumSet using add () : [MEDIUM] EnumSet using addAll () : [SMALL, MEDIUM, LARGE, EXTRALARGE]
在上面的示例中,我们使用addAll()方法将枚举集size1的所有元素插入到枚举集size2中。
也可以使用addAll()将其他集合中的元素(例如ArrayList,LinkedList等)插入到枚举集中。
获取元素 要访问一个枚举集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.EnumSet;import java.util.Iterator;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); Iterator<Size> iterate = sizes.iterator(); System.out.print("EnumSet: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 EnumSet: SMALL, MEDIUM, LARGE, EXTRALARGE
注意:
hasNext() - 如果枚举集中存在下一个元素,则返回true
next() - 返回枚举集中的下一个元素
remove
remove() - 从枚举集中删除指定的元素
removeAll() - 从枚举集中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.EnumSet;class Main { enum Size { SMALL, MEDIUM, LARGE, EXTRALARGE } public static void main (String[] args) { EnumSet<Size> sizes = EnumSet.allOf(Size.class); System.out.println("EnumSet: " + sizes); boolean value1 = sizes.remove(Size.MEDIUM); System.out.println("Is MEDIUM removed? " + value1); boolean value2 = sizes.removeAll(sizes); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE] Is MEDIUM removed? true Are all elements removed? true
其它方法
Method
Description
copyOf()
创建EnumSet的副本
contains()
在EnumSet中搜索指定的元素并返回布尔结果
isEmpty()
检查EnumSet是否为空
size()
返回EnumSet的大小
clear()
从EnumSet中删除所有元素
Clonable 和 Serializable 接口 EnumSet类还实现了Cloneable和Serializable接口。
Clonable
它允许EnumSet类制作该类实例的副本。
Serializable
每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。Serializable接口允许对类进行序列化。这意味着可以将实现Serializable的类的对象转换为位或字节。
EnumSet 好处 与其他set实现(例如HashSet,TreeSet)相比,EnumSet提供了一种存储枚举值的有效方法。
枚举集仅存储特定枚举的枚举值。因此,JVM已经知道该集合的所有可能值。
这就是为什么枚举集在内部被实现为一系列Bits的原因。Bits指定元素是否存在于枚举集中。
如果集合中存在该元素,则将其对应的位打开。
Javacollections framework的LinkedHashSet类提供了哈希表和链表数据结构的功能。
LinkedHashSet的元素存储在类似于HashSet的哈希表中
但是,LinkedHashSet在内部为其所有元素维护一个双链表。链表定义了在哈希表中插入元素的顺序。
创建 LinkedHashSet 为了创建链接的哈希集,我们必须首先导入java.util.LinkedHashSet包。
1 2 LinkedHashSet<Integer> numbers = new LinkedHashSet<>(8 , 0.75 );
注意,新的LinkedHashSet <>(8,0.75)部分。在这里,第一个参数是容量,第二个参数是负载系数。
capacity - 该哈希集的容量为8。意味着,它可以存储8个元素。
loadFactor - 此哈希集的负载系数为0.6。这意味着,只要我们的哈希表填充了60%,元素就会移到新哈希表中,其大小是原始哈希表的两倍。
注意:capacity 和 loadFactor默认值分别是 16,0.75;
LinkedHashSet 中的方法 LinkedHashSet类提供的方法使我们可以对链表的哈希集执行各种操作。
插入元素
add() - 将指定的元素插入到链表的哈希集中
addAll() - 将指定集合的所有元素插入到链接的哈希集中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> evenNumber = new LinkedHashSet<>(); evenNumber.add(2 ); evenNumber.add(4 ); evenNumber.add(6 ); System.out.println("LinkedHashSet: " + evenNumber); LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.addAll(evenNumber); numbers.add(5 ); System.out.println("New LinkedHashSet: " + numbers); } }
输出:
1 2 LinkedHashSet: [2 , 4 , 6 ] New LinkedHashSet: [2 , 4 , 6 , 5 ]
获取元素 要访问链表的哈希集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.LinkedHashSet;import java.util.Iterator;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("LinkedHashSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("LinkedHashSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 LinkedHashSet: [2 , 5 , 6 ] LinkedHashSet using Iterator: 2 , 5 , 6 ,
注意:
hasNext() - 如果LinkedHashSet中存在下一个元素,则返回true.
next() - 返回LinkedHashSet中的下一个元素
移除元素
remove() - 从LinkedHashSet中删除指定的元素
removeAll() -从LinkedHashSet中删除所有的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("LinkedHashSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 LinkedHashSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Set 操作符 LinkedHashSet类的各种方法也可以用于执行各种集合操作。
Union 两个执行两个集合之间的联合,我们可以使用addAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("LinkedHashSet1: " + evenNumbers); LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(1 ); numbers.add(3 ); System.out.println("LinkedHashSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 4 ] LinkedHashSet2: [1 , 3 ] Union is: [1 , 3 , 2 , 4 ]
Intersection 为了执行两个集合之间的交集,我们可以使用retainAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("LinkedHashSet1: " + primeNumbers); LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("LinkedHashSet2: " + evenNumbers); evenNumbers.retainAll(primeNumbers); System.out.println("Intersection is: " + evenNumbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 3 ] LinkedHashSet2: [2 , 4 ] Intersection is: [2 ]
Difference 要计算两组之间的差异,我们可以使用removeAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); primeNumbers.add(5 ); System.out.println("LinkedHashSet1: " + primeNumbers); LinkedHashSet<Integer> oddNumbers = new LinkedHashSet<>(); oddNumbers.add(1 ); oddNumbers.add(3 ); oddNumbers.add(5 ); System.out.println("LinkedHashSet2: " + oddNumbers); primeNumbers.removeAll(oddNumbers); System.out.println("Difference : " + primeNumbers); } }
输出:
1 2 3 LinkedHashSet1: [2 , 3 , 5 ] LinkedHashSet2: [1 , 3 , 5 ] Difference: [2 ]
Subset 为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.LinkedHashSet;class Main { public static void main (String[] args) { LinkedHashSet<Integer> numbers = new LinkedHashSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("LinkedHashSet1: " + numbers); LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("LinkedHashSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is LinkedHashSet2 is subset of LinkedHashSet1? " + result); } }
输出:
1 2 3 LinkedHashSet1: [1 , 2 , 3 , 4 ] LinkedHashSet2: [2 , 3 ] Is LinkedHashSet2 is a subset of LinkedHashSet1? true
LinkedHashSet其它方法
Method
Description
clone()
创建 LinkedHashSet副本
contains()
在LinkedHashSet中搜索指定的元素,并返回布尔结果
isEmpty()
检查LinkedHashSet是否为空
size()
返回`LinkedHashSet的大小
clear()
从LinkedHashSet中删除所有元素
LinkedHashSet Vs. HashSet LinkedHashSet和HashSet都实现Set接口。但是,它们之间存在一些差异。
LinkedHashSet在内部维护一个链表。因此,它保持其元素的插入顺序。
LinkedHashSet类比HashSet需要更多的存储空间。这是因为LinkedHashSet在内部维护链接列表。
LinkedHashSet的性能比HashSet慢。这是因为LinkedHashSet中存在链表。
LinkedHashSet Vs. TreeSet 这是LinkedHashSet和TreeSet之间的主要区别:
TreeSet类实现SortedSet接口。
TreeSet通常比LinkedHashSet慢。这是因为每当元素添加到TreeSet时,它都必须执行排序操作。
LinkedHashSet允许插入空值。但是,我们不能将空值插入`TreeSet。
Java collections framework的SortedSet接口用于将元素以某种顺序存储在集合中。
实现SortedSet的类 为了使用SortedSet接口的功能,我们需要使用实现该接口的TreeSet类。
怎么使用 SortedSet 要使用SortedSet,我们必须首先导入java.util.SortedSet包。
1 2 SortedSet<String> animals = new TreeSet<>();
在这里,我们没有使用任何参数来创建排序集。因此,该集合将自然排序。
SortedSet中的方法 SortedSet接口包含Set接口的所有方法。这是因为Set是SortedSet的超级接口。
除了Set接口中包含的方法外,SortedSet接口还包括以下方法:
comparator() - 返回一个比较器,该比较器可用于对集合中的元素进行排序
first() - 返回集合的第一个元素
last() - 返回集合的最后一个元素
headSet(element) - 返回指定元素之前的所有元素
tailSet(element) - 在指定元素之后(包括指定元素)返回集合中的所有元素
subSet(element1, element2) - 返回element1和element2之间的所有元素,包括element1
实现SortedSet的类 TreeSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.SortedSet;import java.util.TreeSet;class Main { public static void main (String[] args) { SortedSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("SortedSet: " + numbers); int firstNumber = numbers.first(); System.out.println("First Number: " + firstNumber); int lastNumber = numbers.last(); System.out.println("Last Number: " + lastNumber); boolean result = numbers.remove(2 ); System.out.println("Is the number 2 removed? " + result); } }
输出:
1 2 3 4 SortedSet: [1 , 2 , 3 , 4 ] First Number: 1 Last Number: 4 Is the number 2 removed? true
Java Collections framework的NavigableSet接口提供了在集合之间导航的功能。
实现NavigableSet的类 为了使用NavigableSet接口的功能,我们需要使用实现NavigableSet的TreeSet类。
怎么使用 NavigableSet 在Java中,我们必须导入java.util.NavigableSet包才能使用NavigableSet。
1 2 NavigableSet<String> numbers = new TreeSet<>();
NavigableSet中的方法 NavigableSet被视为SortedSet的一种。这是因为NavigableSet扩展了SortedSet接口。
但是,在NavigableSet中,对SortedSet的某些方法(headSet(),tailSet()和subSet())进行了不同的定义。
headSet(element, booleanValue) headSet()方法返回指定元素之前的可导航集合的所有元素(作为参数传递)。booleanValue参数是可选的。其默认值为false。如果将true作为booleanValue传递,则该方法返回指定元素之前的所有元素,包括指定元素。
tailSet(element, booleanValue) tailSet()方法在包含指定元素的指定元素(作为参数传递)之后返回可导航集中的所有元素。
booleanValue参数是可选的。其默认值为true。
如果将false作为booleanValue传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。
subSet(e1,bv1,e2,bv2) subSet()方法返回e1和e2之间的所有元素,包括e1。
bv1和bv2是可选参数。 bv1的默认值为true,bv2的默认值为false。
如果将false作为bv1传递,则该方法返回e1和e2之间的所有元素,而不包括e1。
如果将true作为bv2传递,则该方法返回e1和e2之间的所有元素,包括e1。
Navigation 中的方法 NavigableSet提供了各种可用于导航其元素的方法。
descendingSet() - 反转集合中元素的顺序
descendingIterator() - 返回一个迭代器,该迭代器可用于以相反的顺序迭代集合
ceiling() - 返回大于或等于指定元素的那些元素中的最低元素
floor() - 返回小于或等于指定元素的那些元素中最大的元素
higher() - 返回大于指定元素的那些元素中的最低元素
lower() - 返回小于指定元素的那些元素中最大的元素
pollFirst() - 返回并从集合中删除第一个元素
pollLast() - 返回并从集合中删除最后一个元素
实现 NavigableSet接口的类TreeSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.util.NavigableSet;import java.util.TreeSet;class Main { public static void main (String[] args) { NavigableSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("NavigableSet: " + numbers); int firstElement = numbers.first(); System.out.println("First Number: " + firstElement); int lastElement = numbers.last(); System.out.println("Last Element: " + lastElement); int number1 = numbers.pollFirst(); System.out.println("Removed First Element: " + number1); int number2 = numbers.pollLast(); System.out.println("Removed Last Element: " + number2); } }
输出:
1 2 3 4 5 NavigableSet: [1 , 2 , 3 ] First Element: 1 Last Element: 3 Removed First Element: 1 Removed Last Element: 3
Java collections framework的TreeSet类提供树数据结构的功能。
创建 TreeSet 为了创建树集,我们必须首先导入java.util.TreeSet包。
1 TreeSet<Integer> numbers = new TreeSet<>();
在这里,我们创建了一个不带任何参数的TreeSet。在这种情况下,TreeSet中的元素会自然排序(升序)。
但是,我们可以使用Comparator接口自定义元素的排序。
TreeSet中的方法 TreeSet类提供了各种方法,使我们可以对集合执行各种操作。
插入元素
add() - 将指定的元素插入集合
addAll() - 将指定集合的所有元素插入集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); evenNumbers.add(6 ); System.out.println("TreeSet: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.addAll(evenNumbers); System.out.println("New TreeSet: " + numbers); } }
输出:
1 2 TreeSet: [2 , 4 , 6 ] New TreeSet: [1 , 2 , 4 , 6 ]
获取元素 要访问树集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;import java.util.Iterator;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); Iterator<Integer> iterate = numbers.iterator(); System.out.print("TreeSet using Iterator: " ); while (iterate.hasNext()) { System.out.print(iterate.next()); System.out.print(", " ); } } }
输出:
1 2 TreeSet: [2 , 5 , 6 ] TreeSet using Iterator: 2 , 5 , 6 ,
删除元素
remove() - 从集合中移除指定的元素
removeAll() - 从集合中删除所有元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); boolean value1 = numbers.remove(5 ); System.out.println("Is 5 removed? " + value1); boolean value2 = numbers.removeAll(numbers); System.out.println("Are all elements removed? " + value2); } }
输出:
1 2 3 TreeSet: [2 , 5 , 6 ] Is 5 removed? true Are all elements removed? true
Navigation中的方法 由于TreeSet类实现了NavigableSet,因此它提供了各种方法来浏览树集的元素。
first() and last()
first() - 返回集合的第一个元素
last() - 返回集合的最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); int first = numbers.first(); System.out.println("First Number: " + first); int last = numbers.last(); System.out.println("Last Number: " + last); } }
输出:
1 2 3 TreeSet: [2 , 5 , 6 ] First Number: 2 Last Number: 6
ceiling(), floor(), higher() and lower()
higher(element) - 返回大于指定元素的那些元素中的最低元素
lower(element) - 返回小于指定元素的那些元素中最大的元素
ceiling(element) - 返回大于指定元素的那些元素中的最低元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
floor(element) - 返回小于指定元素的那些元素中最大的元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using higher: " + numbers.higher(4 )); System.out.println("Using lower: " + numbers.lower(4 )); System.out.println("Using ceiling: " + numbers.ceiling(4 )); System.out.println("Using floor: " + numbers.floor(3 )); } }
输出:
1 2 3 4 5 TreeSet: [2 , 4 , 5 , 6 ] Using higher: 5 Using lower: 2 Using ceiling: 4 Using floor: 2
pollfirst() and pollLast()
pollFirst() - 返回并从集合中删除第一个元素
pollLast() - 返回并从集合中删除最后一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Removed First Element: " + numbers.pollFirst()); System.out.println("Removed Last Element: " + numbers.pollLast()); System.out.println("New TreeSet: " + numbers); } }
输出:
1 2 3 4 TreeSet: [2 , 4 , 5 , 6 ] Removed First Element: 2 Removed Last Element: 6 New TreeSet: [4 , 5 ]
headSet(element, booleanValue) headSet()方法返回指定元素(作为参数传递)之前的树集的所有元素。booleanValue参数是可选的。其默认值为false。
如果将true作为booleanValue传递,则该方法返回指定元素之前的所有元素,包括指定元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using headSet without boolean value: " + numbers.headSet(5 )); System.out.println("Using headSet with boolean value: " + numbers.headSet(5 , true )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using headSet without boolean value: [2 , 4 ] Using headSet with boolean value: [2 , 4 , 5 ]
tailSet(element, booleanValue) tailSet()方法返回包含指定元素的指定元素(作为参数传递)之后的树集的所有元素.booleanValue参数是可选的。其默认值为true。
如果将false作为booleanValue传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using tailSet without boolean value: " + numbers.tailSet(4 )); System.out.println("Using tailSet with boolean value: " + numbers.tailSet(4 , false )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using tailSet without boolean value: [4 , 5 , 6 ] Using tailSet with boolean value: [5 , 6 ]
subSet(e1, bv1, e2, bv2) subSet()方法返回e1和e2之间的所有元素,包括e1。
bv1和bv2是可选参数。 bv1的默认值为true,bv2的默认值为false。
如果将false作为bv1传递,则该方法返回e1和e2之间的所有元素,而不包括e1。
如果将true作为bv2传递,则该方法返回e1和e2之间的所有元素,包括e1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(2 ); numbers.add(5 ); numbers.add(4 ); numbers.add(6 ); System.out.println("TreeSet: " + numbers); System.out.println("Using subSet without boolean value: " + numbers.subSet(4 , 6 )); System.out.println("Using subSet with boolean value: " + numbers.subSet(4 , false , 6 , true )); } }
输出:
1 2 3 TreeSet: [2 , 4 , 5 , 6 ] Using subSet without boolean value: [4 , 5 ] Using subSet with boolean value: [5 , 6 ]
集合操作符 TreeSet类的方法还可用于执行各种集合操作。
Union 为了执行两个集合之间的联合,我们使用addAll()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("TreeSet2: " + numbers); numbers.addAll(evenNumbers); System.out.println("Union is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 ] Union is: [1 , 2 , 3 , 4 ]
Intersection 为了执行两个集合之间的交集,我们使用了retainAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("TreeSet2: " + numbers); numbers.retainAll(evenNumbers); System.out.println("Intersection is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 ] Intersection is: [2 ]
Difference 要计算两组之间的差异,我们可以使用removeAll()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;;class Main { public static void main (String[] args) { TreeSet<Integer> evenNumbers = new TreeSet<>(); evenNumbers.add(2 ); evenNumbers.add(4 ); System.out.println("TreeSet1: " + evenNumbers); TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("TreeSet2: " + numbers); numbers.removeAll(evenNumbers); System.out.println("Difference is: " + numbers); } }
输出:
1 2 3 TreeSet1: [2 , 4 ] TreeSet2: [1 , 2 , 3 , 4 ] Difference is: [1 , 3 ]
Subset 要检查一个集合是否是另一个集合的子集,我们使用containsAll()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.TreeSet;class Main { public static void main (String[] args) { TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(4 ); System.out.println("TreeSet1: " + numbers); TreeSet<Integer> primeNumbers = new TreeSet<>(); primeNumbers.add(2 ); primeNumbers.add(3 ); System.out.println("TreeSet2: " + primeNumbers); boolean result = numbers.containsAll(primeNumbers); System.out.println("Is TreeSet2 subset of TreeSet1? " + result); } }
输出:
1 2 3 TreeSet1: [1 , 2 , 3 , 4 ] TreeSet2: [2 , 3 ] Is TreeSet2 subset of TreeSet1? True
TreeSet中其它方法
Method
Description
clone()
创建TreeSet的副本
contains()
在TreeSet中搜索指定的元素并返回布尔结果
isEmpty()
检查TreeSet是否为空
size()
返回TreeSet的大小
clear()
从TreeSet中删除所有元素
TreeSet Vs. HashSet TreeSet和HashSet都实现Set接口。但是,它们之间存在一些差异。
与HashSet不同,TreeSet中的元素以某种顺序存储。这是因为TreeSet也实现了SortedSet接口。
TreeSet提供了一些易于导航的方法。例如first(),last(),headSet(),tailSet()等。这是因为TreeSet还实现了NavigableSet接口。
HashSet比TreeSet快,对于诸如add,remove,contains和size之类的基本操作。
TreeSet Comparator 我们可以自定义元素的顺序。为此,我们需要基于对树集中的哪些元素进行排序来创建自己的Comparator类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.util.TreeSet;import java.util.Comparator;class Main { public static void main (String[] args) { TreeSet<String> animals = new TreeSet<>(new CustomComparator()); animals.add("Dog" ); animals.add("Zebra" ); animals.add("Cat" ); animals.add("Horse" ); System.out.println("TreeSet: " + animals); } public static class CustomComparator implements Comparator <String > { @Override public int compare (String animal1, String animal2) { int value = animal1.compareTo(animal2); if (value > 0 ) { return -1 ; } else if (value < 0 ) { return 1 ; } else { return 0 ; } } } }
输出:
1 TreeSet: [Zebra, Horse, Dog, Cat]
在上面的示例中,我们创建了一个树集,将CustomComparator类作为参数传递。
CustomComparator类实现Comparator接口
然后,我们重写compare()方法。现在,该方法将以相反的顺序对元素进行排序.
Java collection framework的Iterator接口允许我们访问集合的元素。它具有一个子接口ListIterator。
所有Java集合都包含iterator()方法。此方法返回用于迭代集合元素的迭代器实例。
Iterator 中的方法 Iterator接口提供了4种方法,可用于对集合元素执行各种操作。
hasNext() - 如果集合中存在一个元素,则返回true
next() - 返回集合的下一个元素
remove() - 删除next()返回的最后一个元素
forEachRemaining() - 对集合的每个剩余元素执行指定的操作
例子🌰 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.ArrayList;import java.util.Iterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); Iterator<Integer> iterate = numbers.iterator(); int number = iterate.next(); System.out.println("Accessed Element: " + number); iterate.remove(); System.out.println("Removed Element: " + number); System.out.print("Updated ArrayList: " ); while (iterate.hasNext()) { iterate.forEachRemaining((value) -> System.out.print(value + ", " )); } } }
输出:
1 2 3 4 ArrayList: [1 , 3 , 2 ] Acessed Element: 1 Removed Element: 1 Updated ArrayList: 3 , 2 ,
在上面的示例中
1 iterate.forEachRemaining((value) -> System.put.print(value + ", " ));
在这里,我们将lambda表达式作为forEachRemaining()方法的参数传递。现在,该方法将打印数组列表中的所有其余元素。
Java collection framework 的ListIterator接口提供了访问list元素的功能.它是双向的。这意味着它允许我们在两个方向上迭代列表的元素。
List接口提供了一个ListIterator()方法,该方法返回ListIterator 接口的一个实例。
ListIterator中的方法
hasNext() - 如果列表中存在一个元素,则返回true
next() - 返回列表的下一个元素
nextIndex() - 返回下个元素的索引.(调用next()方法获取的元素)
previous() - 返回列表的上一个元素
previousIndex() - 返回列表的上一个元素索引(调用previousIndex()方法获取的元素)
remove() - 删除由next()或previous()返回的元素
set() - 将next()或previous()返回的元素替换为指定的元素
例子🌰1 在下面的示例中,我们在数组列表中实现了ListIterator接口的next(),nextIndex()和hasNext()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.ArrayList;import java.util.ListIterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); ListIterator<Integer> iterate = numbers.listIterator(); int number1 = iterate.next(); System.out.println("Next Element: " + number1); int index1 = iterate.nextIndex(); System.out.println("Position of Next Element: " + index1); System.out.println("Is there any next element? " + iterate.hasNext()); } }
输出:
1 2 3 4 ArrayList: [1 , 3 , 2 ] Next Element: 1 Position of Next Element: 1 Is there any next element? true
例子🌰2 在下面的示例中,我们在数组列表中实现了ListIterator接口的previous()和previousIndex()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.ArrayList;import java.util.ListIterator;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList: " + numbers); ListIterator<Integer> iterate = numbers.listIterator(); iterate.next(); iterate.next(); int number1 = iterate.previous(); System.out.println("Previous Element: " + number1); int index1 = iterate.previousIndex(); System.out.println("Position of the Previous element: " + index1); } }
输出:
1 2 3 ArrayList: [1 , 3 , 2 ] Previous Element: 3 Position of the Previous Element: 0
在上面的示例中,最初,Iterator的实例在1之前。由于在1之前没有元素,因此调用previous()方法将引发异常。
然后,我们使用了next()方法两次。现在,Iterator实例将在3到2之间。因此,previous()方法返回3。
Java collection framework提供了各种算法,可用于处理存储在数据结构中的元素。
Java中的算法是静态方法,可用于对集合执行各种操作。
由于算法可以用于各种集合,因此也称为通用算法。
使用sort()排序 sort()方法用于对元素进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Collections;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(4 ); numbers.add(2 ); numbers.add(3 ); System.out.println("Unsorted ArrayList: " + numbers); Collections.sort(numbers); System.out.println("Sorted ArrayList: " + numbers); } }
输出:
1 2 Unsorted ArrayList: [4 , 2 , 3 ] Sorted ArrayList: [2 , 3 , 4 ]
在此,排序以自然顺序(升序)进行。但是,我们可以使用Comparator接口自定义sort()方法的排序顺序。
随机排序shuffle() shuffle()方法用于破坏数据结构中存在的任何种类的顺序,它与排序相反。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.ArrayList;import java.util.Collections;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); System.out.println("Sorted ArrayList: " + numbers); Collections.shuffle(numbers); System.out.println("ArrayList using shuffle: " + numbers); } }
输出:
1 2 Sorted ArrayList: [1 , 2 , 3 ] ArrayList using shuffle: [2 , 1 , 3 ]
当我们运行程序时,shuffle()方法将返回随机输出。
常规数据操作 在Java中,collections framework提供了可用于处理数据的不同方法。
reverse() - 反转元素的顺序
fill() - 用指定值替换集合中的每个元素
copy() - 创建从指定源到目标的元素副本
swap() - 交换集合中两个元素的位置
addAll() - 将一个集合的所有元素添加到其他集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); System.out.println("ArrayList1: " + numbers); Collections.reverse(numbers); System.out.println("Reversed ArrayList1: " + numbers); Collections.swap(numbers, 0 , 1 ); System.out.println("ArrayList1 using swap(): " + numbers); ArrayList<Integer> newNumbers = new ArrayList<>(); newNumbers.addAll(numbers); System.out.println("ArrayList2 using addAll(): " + newNumbers); Collections.fill(numbers, 0 ); System.out.println("ArrayList1 using fill(): " + numbers); Collections.copy(newNumbers, numbers); System.out.println("ArrayList2 using copy(): " + newNumbers); } }
输出:
1 2 3 4 5 6 ArrayList1: [1 , 2 ] Reversed ArrayList1: [2 , 1 ] ArrayList1 Using swap () : [1, 2] ArrayList2 using addALl () : [1, 2] ArrayList1 using fill () : [0, 0] ArrayList2 using copy () : [0, 0]
注意:在执行copy()方法时,两个列表的大小应相同。
使用binarySearch()搜索 binarySearch()方法搜索指定的元素。它返回元素在指定集合中的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); int pos = Collections.binarySearch(numbers, 3 ); System.out.println("The position of 3 is " + pos); } }
输出:
注意:应该在执行binarySearch()方法之前对集合进行排序。
Composition
frequency() - 返回元素在集合中存在的次数
disjoint() - 检查两个集合是否不相交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); numbers.add(2 ); System.out.println("ArrayList1: " + numbers); int count = Collections.frequency(numbers, 2 ); System.out.println("Count of 2: " + count); ArrayList<Integer> newNumbers = new ArrayList<>(); newNumbers.add(5 ); newNumbers.add(6 ); System.out.println("ArrayList2: " + newNumbers); boolean value = Collections.disjoint(numbers, newNumbers); System.out.println("Two lists are disjoint: " + value); } }
输出:
1 2 3 4 ArrayList1: [1 , 2 , 3 , 2 ] Count of 2 : 2 ArrayList2: [5 , 6 ] Two lists are disjoint: true
寻找极限值 Java collections framework 的min()和max()方法分别用于查找最小和最大元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.Collections;import java.util.ArrayList;class Main { public static void main (String[] args) { ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(1 ); numbers.add(2 ); numbers.add(3 ); int min = Collections.min(numbers); System.out.println("Minimum Element: " + min); int max = Collections.max(numbers); System.out.println("Maximum Element: " + max); } }
输出:
1 2 Minimum Element: 1 Maximum Element: 3